blob: d9369190cf0aafff0ca48816f03604d9fd4576e6 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.conscrypt;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public final class OpenSSLECKeyPairGenerator extends KeyPairGenerator {
private static final String ALGORITHM = "EC";
private static final int DEFAULT_KEY_SIZE = 256;
private static final Map<Integer, String> SIZE_TO_CURVE_NAME = new HashMap<Integer, String>();
static {
/* NIST curves */
SIZE_TO_CURVE_NAME.put(224, "secp224r1");
SIZE_TO_CURVE_NAME.put(256, "prime256v1");
SIZE_TO_CURVE_NAME.put(384, "secp384r1");
SIZE_TO_CURVE_NAME.put(521, "secp521r1");
}
private OpenSSLECGroupContext group;
public OpenSSLECKeyPairGenerator() {
super(ALGORITHM);
}
@Override
public KeyPair generateKeyPair() {
if (group == null) {
final String curveName = SIZE_TO_CURVE_NAME.get(DEFAULT_KEY_SIZE);
group = OpenSSLECGroupContext.getCurveByName(curveName);
if (group == null) {
throw new RuntimeException("Curve not recognized: " + curveName);
}
}
final OpenSSLKey key = new OpenSSLKey(
NativeCrypto.EC_KEY_generate_key(group.getNativeRef()));
return new KeyPair(new OpenSSLECPublicKey(group, key), new OpenSSLECPrivateKey(group, key));
}
@Override
public void initialize(int keysize, SecureRandom random) {
final String name = SIZE_TO_CURVE_NAME.get(keysize);
if (name == null) {
throw new InvalidParameterException("unknown key size " + keysize);
}
/*
* Store the group in a temporary variable until we know this is a valid
* group.
*/
final OpenSSLECGroupContext possibleGroup = OpenSSLECGroupContext.getCurveByName(name);
if (possibleGroup == null) {
throw new InvalidParameterException("unknown curve " + name);
}
group = possibleGroup;
}
@Override
public void initialize(AlgorithmParameterSpec param, SecureRandom random)
throws InvalidAlgorithmParameterException {
if (param instanceof ECParameterSpec) {
ECParameterSpec ecParam = (ECParameterSpec) param;
group = OpenSSLECGroupContext.getInstance(ecParam);
} else if (param instanceof ECGenParameterSpec) {
ECGenParameterSpec ecParam = (ECGenParameterSpec) param;
final String curveName = ecParam.getName();
/*
* Store the group in a temporary variable until we know this is a
* valid group.
*/
final OpenSSLECGroupContext possibleGroup = OpenSSLECGroupContext
.getCurveByName(curveName);
if (possibleGroup == null) {
throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
}
group = possibleGroup;
} else {
throw new InvalidAlgorithmParameterException(
"parameter must be ECParameterSpec or ECGenParameterSpec");
}
}
/** For testing. */
public static void assertCurvesAreValid() {
ArrayList<String> invalidCurves = new ArrayList<>();
for (String curveName : SIZE_TO_CURVE_NAME.values()) {
if (OpenSSLECGroupContext.getCurveByName(curveName) == null) {
invalidCurves.add(curveName);
}
}
if (invalidCurves.size() > 0) {
throw new AssertionError("Invalid curve names: "
+ Arrays.toString(invalidCurves.toArray()));
}
}
}