19d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root/*
29d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * Copyright (C) 2012 The Android Open Source Project
39d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root *
49d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
59d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * you may not use this file except in compliance with the License.
69d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * You may obtain a copy of the License at
79d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root *
89d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
99d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root *
109d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * Unless required by applicable law or agreed to in writing, software
119d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
129d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * See the License for the specific language governing permissions and
149d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root * limitations under the License.
159d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root */
169d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
1738375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Rootpackage org.conscrypt;
189d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
199d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.InvalidAlgorithmParameterException;
209d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.InvalidParameterException;
219d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.KeyPair;
229d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.KeyPairGenerator;
239d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.SecureRandom;
249d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.spec.AlgorithmParameterSpec;
259d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.spec.ECGenParameterSpec;
269d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.security.spec.ECParameterSpec;
279d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.util.HashMap;
289d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootimport java.util.Map;
299d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
309d2fb535e5d43ad34af09195d490da18a7694a48Kenny Rootpublic final class OpenSSLECKeyPairGenerator extends KeyPairGenerator {
319d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    private static final String ALGORITHM = "EC";
329d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
339d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    private static final int DEFAULT_KEY_SIZE = 192;
349d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
359d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    private static final Map<Integer, String> SIZE_TO_CURVE_NAME = new HashMap<Integer, String>();
369d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
379d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    static {
389d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        /* NIST curves */
399d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        SIZE_TO_CURVE_NAME.put(192, "prime192v1");
403fefbd8abaf356e842705f8ebd24b414dcea8aacKenny Root        SIZE_TO_CURVE_NAME.put(224, "secp224r1");
419d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        SIZE_TO_CURVE_NAME.put(256, "prime256v1");
423fefbd8abaf356e842705f8ebd24b414dcea8aacKenny Root        SIZE_TO_CURVE_NAME.put(384, "secp384r1");
433fefbd8abaf356e842705f8ebd24b414dcea8aacKenny Root        SIZE_TO_CURVE_NAME.put(521, "secp521r1");
449d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    }
459d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
469d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    private OpenSSLECGroupContext group;
479d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
489d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    public OpenSSLECKeyPairGenerator() {
499d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        super(ALGORITHM);
509d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    }
519d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
529d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    @Override
539d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    public KeyPair generateKeyPair() {
549d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        if (group == null) {
559d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            final String curveName = SIZE_TO_CURVE_NAME.get(DEFAULT_KEY_SIZE);
569d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            group = OpenSSLECGroupContext.getCurveByName(curveName);
579d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        }
589d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
599d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        final OpenSSLKey key = new OpenSSLKey(NativeCrypto.EC_KEY_generate_key(group.getContext()));
609d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        return new KeyPair(new OpenSSLECPublicKey(group, key), new OpenSSLECPrivateKey(group, key));
619d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    }
629d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
639d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    @Override
649d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    public void initialize(int keysize, SecureRandom random) {
659d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        final String name = SIZE_TO_CURVE_NAME.get(keysize);
669d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        if (name == null) {
679d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            throw new InvalidParameterException("unknown key size " + keysize);
689d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        }
699d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
709d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        /*
719d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root         * Store the group in a temporary variable until we know this is a valid
729d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root         * group.
739d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root         */
749d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        final OpenSSLECGroupContext possibleGroup = OpenSSLECGroupContext.getCurveByName(name);
759d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        if (possibleGroup == null) {
769d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            throw new InvalidParameterException("unknown curve " + name);
779d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        }
789d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
799d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        group = possibleGroup;
809d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    }
819d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
829d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    @Override
839d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    public void initialize(AlgorithmParameterSpec param, SecureRandom random)
849d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            throws InvalidAlgorithmParameterException {
859d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        if (param instanceof ECParameterSpec) {
869d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            ECParameterSpec ecParam = (ECParameterSpec) param;
879d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
889d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            group = OpenSSLECGroupContext.getInstance(ecParam);
899d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        } else if (param instanceof ECGenParameterSpec) {
909d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            ECGenParameterSpec ecParam = (ECGenParameterSpec) param;
919d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
929d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            final String curveName = ecParam.getName();
939d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
949d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            /*
959d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root             * Store the group in a temporary variable until we know this is a
969d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root             * valid group.
979d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root             */
989d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            final OpenSSLECGroupContext possibleGroup = OpenSSLECGroupContext
999d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root                    .getCurveByName(curveName);
1009d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            if (possibleGroup == null) {
1019d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root                throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
1029d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            }
1039d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root
1049d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            group = possibleGroup;
1059d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        } else {
1069d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root            throw new InvalidAlgorithmParameterException(
1079d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root                    "parameter must be ECParameterSpec or ECGenParameterSpec");
1089d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root        }
1099d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root    }
1109d2fb535e5d43ad34af09195d490da18a7694a48Kenny Root}
111