• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.conscrypt;
18 
19 import java.security.InvalidAlgorithmParameterException;
20 import java.security.InvalidParameterException;
21 import java.security.KeyPair;
22 import java.security.KeyPairGenerator;
23 import java.security.SecureRandom;
24 import java.security.spec.AlgorithmParameterSpec;
25 import java.security.spec.ECGenParameterSpec;
26 import java.security.spec.ECParameterSpec;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.Map;
31 
32 public final class OpenSSLECKeyPairGenerator extends KeyPairGenerator {
33     private static final String ALGORITHM = "EC";
34 
35     private static final int DEFAULT_KEY_SIZE = 256;
36 
37     private static final Map<Integer, String> SIZE_TO_CURVE_NAME = new HashMap<Integer, String>();
38 
39     static {
40         /* NIST curves */
41         SIZE_TO_CURVE_NAME.put(224, "secp224r1");
42         SIZE_TO_CURVE_NAME.put(256, "prime256v1");
43         SIZE_TO_CURVE_NAME.put(384, "secp384r1");
44         SIZE_TO_CURVE_NAME.put(521, "secp521r1");
45     }
46 
47     private OpenSSLECGroupContext group;
48 
OpenSSLECKeyPairGenerator()49     public OpenSSLECKeyPairGenerator() {
50         super(ALGORITHM);
51     }
52 
53     @Override
generateKeyPair()54     public KeyPair generateKeyPair() {
55         if (group == null) {
56             final String curveName = SIZE_TO_CURVE_NAME.get(DEFAULT_KEY_SIZE);
57             group = OpenSSLECGroupContext.getCurveByName(curveName);
58             if (group == null) {
59                 throw new RuntimeException("Curve not recognized: " + curveName);
60             }
61         }
62 
63         final OpenSSLKey key = new OpenSSLKey(
64                 NativeCrypto.EC_KEY_generate_key(group.getNativeRef()));
65         return new KeyPair(new OpenSSLECPublicKey(group, key), new OpenSSLECPrivateKey(group, key));
66     }
67 
68     @Override
initialize(int keysize, SecureRandom random)69     public void initialize(int keysize, SecureRandom random) {
70         final String name = SIZE_TO_CURVE_NAME.get(keysize);
71         if (name == null) {
72             throw new InvalidParameterException("unknown key size " + keysize);
73         }
74 
75         /*
76          * Store the group in a temporary variable until we know this is a valid
77          * group.
78          */
79         final OpenSSLECGroupContext possibleGroup = OpenSSLECGroupContext.getCurveByName(name);
80         if (possibleGroup == null) {
81             throw new InvalidParameterException("unknown curve " + name);
82         }
83 
84         group = possibleGroup;
85     }
86 
87     @Override
initialize(AlgorithmParameterSpec param, SecureRandom random)88     public void initialize(AlgorithmParameterSpec param, SecureRandom random)
89             throws InvalidAlgorithmParameterException {
90         if (param instanceof ECParameterSpec) {
91             ECParameterSpec ecParam = (ECParameterSpec) param;
92 
93             group = OpenSSLECGroupContext.getInstance(ecParam);
94         } else if (param instanceof ECGenParameterSpec) {
95             ECGenParameterSpec ecParam = (ECGenParameterSpec) param;
96 
97             final String curveName = ecParam.getName();
98 
99             /*
100              * Store the group in a temporary variable until we know this is a
101              * valid group.
102              */
103             final OpenSSLECGroupContext possibleGroup = OpenSSLECGroupContext
104                     .getCurveByName(curveName);
105             if (possibleGroup == null) {
106                 throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
107             }
108 
109             group = possibleGroup;
110         } else {
111             throw new InvalidAlgorithmParameterException(
112                     "parameter must be ECParameterSpec or ECGenParameterSpec");
113         }
114     }
115 
116     /** For testing. */
assertCurvesAreValid()117     public static void assertCurvesAreValid() {
118         ArrayList<String> invalidCurves = new ArrayList<>();
119         for (String curveName : SIZE_TO_CURVE_NAME.values()) {
120             if (OpenSSLECGroupContext.getCurveByName(curveName) == null) {
121                 invalidCurves.add(curveName);
122             }
123         }
124         if (invalidCurves.size() > 0) {
125             throw new AssertionError("Invalid curve names: "
126                     + Arrays.toString(invalidCurves.toArray()));
127         }
128     }
129 }
130