All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openeuler.sun.security.ssl.SM2KeyExchange Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2018, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

package org.openeuler.sun.security.ssl;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.net.ssl.SSLHandshakeException;

import org.openeuler.spec.SM2KeyExchangeParameterSpec;
import org.openeuler.sun.security.ssl.SupportedGroupsExtension.NamedGroup;
import org.openeuler.sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
import org.openeuler.sun.security.ssl.SupportedGroupsExtension.SupportedGroups;

import org.openeuler.sun.security.ssl.GMX509Authentication.GMX509Possession;
import org.openeuler.sun.security.ssl.GMX509Authentication.GMX509Credentials;
import sun.security.util.ECUtil;

final class SM2KeyExchange {
    static final SSLPossessionGenerator poGenerator =
            new SM2PossessionGenerator();
    static final SSLKeyAgreementGenerator sm2KAGenerator =
            new SM2KAGenerator();

    static final class SM2Credentials implements SSLCredentials {
        final ECPublicKey popPublicKey;
        final NamedGroup namedGroup;

        SM2Credentials(ECPublicKey popPublicKey, NamedGroup namedGroup) {
            this.popPublicKey = popPublicKey;
            this.namedGroup = namedGroup;
        }
    }

    static final class SM2Possession implements SSLPossession {
        final ECPrivateKey privateKey;
        final ECPublicKey publicKey;
        final NamedGroup namedGroup;

        SM2Possession(NamedGroup namedGroup, SecureRandom random) {
            try {
                KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("SM2");
                ECGenParameterSpec params =
                        (ECGenParameterSpec) namedGroup.getParameterSpec();
                kpg.initialize(params, random);
                KeyPair kp = kpg.generateKeyPair();
                privateKey = (ECPrivateKey) kp.getPrivate();
                publicKey = (ECPublicKey) kp.getPublic();
            } catch (GeneralSecurityException e) {
                throw new RuntimeException(
                        "Could not generate SM2 keypair", e);
            }

            this.namedGroup = namedGroup;
        }

        SM2Possession(SM2Credentials credentials, SecureRandom random) {
            ECParameterSpec params = credentials.popPublicKey.getParams();
            try {
                KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("SM2");
                kpg.initialize(params, random);
                KeyPair kp = kpg.generateKeyPair();
                privateKey = (ECPrivateKey) kp.getPrivate();
                publicKey = (ECPublicKey) kp.getPublic();
            } catch (GeneralSecurityException e) {
                throw new RuntimeException(
                        "Could not generate SM2 keypair", e);
            }

            this.namedGroup = credentials.namedGroup;
        }

        @Override
        public byte[] encode() {
            return ECUtil.encodePoint(
                    publicKey.getW(), publicKey.getParams().getCurve());
        }
    }

    private static final
            class SM2PossessionGenerator implements SSLPossessionGenerator {
        // Prevent instantiation of this class.
        private SM2PossessionGenerator() {
            // blank
        }

        @Override
        public SSLPossession createPossession(HandshakeContext context) {
            NamedGroup preferableNamedGroup = null;
            ProtocolVersion protocolVersion = context.t12WithGMCipherSuite ?
                    ProtocolVersion.GMTLS : context.negotiatedProtocol;
            if ((context.clientRequestedNamedGroups != null) &&
                    (!context.clientRequestedNamedGroups.isEmpty())) {
                preferableNamedGroup = SupportedGroups.getPreferredGroup(
                        protocolVersion,
                        context.algorithmConstraints,
                        NamedGroupType.NAMED_GROUP_ECDHE,
                        context.clientRequestedNamedGroups);
            } else {
                preferableNamedGroup = SupportedGroups.getPreferredGroup(
                        protocolVersion,
                        context.algorithmConstraints,
                        NamedGroupType.NAMED_GROUP_ECDHE);
            }

            if (preferableNamedGroup != null) {
                return new SM2Possession(preferableNamedGroup,
                            context.sslContext.getSecureRandom());
            }

            // no match found, cannot use this cipher suite.
            //
            return null;
        }
    }

    private static final
            class SM2KAGenerator implements SSLKeyAgreementGenerator {
        // Prevent instantiation of this class.
        private SM2KAGenerator() {
            // blank
        }

        @Override
        public SSLKeyDerivation createKeyDerivation(
                HandshakeContext context) throws IOException {
            SM2Possession sm2Possession = null;
            GMX509Possession gmx509Possession = null;
            for (SSLPossession poss : context.handshakePossessions) {
                if (poss instanceof SM2Possession) {
                    sm2Possession = (SM2Possession) poss;
                } else if (poss instanceof GMX509Possession) {
                    gmx509Possession = (GMX509Possession) poss;
                }
                if (sm2Possession != null && gmx509Possession != null) {
                    break;
                }
            }
            if (sm2Possession == null || gmx509Possession == null) {
                throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
                        "No sufficient sm2 key agreement parameters negotiated");
            }

            SM2Credentials sm2Credentials = null;
            GMX509Credentials gmx509Credentials = null;
            for (SSLCredentials cred : context.handshakeCredentials) {
                if (cred instanceof SM2Credentials) {
                    sm2Credentials = (SM2Credentials)cred;
                } else if (cred instanceof GMX509Credentials) {
                    gmx509Credentials = (GMX509Credentials) cred;
                }
                if (sm2Credentials != null && gmx509Credentials != null) {
                    break;
                }
            }
            if (sm2Credentials == null || gmx509Credentials == null) {
                throw context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
                        "No sufficient sm2 key agreement parameters negotiated");
            }

            return new SM2KAKeyDerivation(context,
                    (ECPrivateKey) gmx509Possession.popEncPrivateKey, (ECPublicKey) gmx509Possession.popEncPublicKey,
                    sm2Possession.privateKey, sm2Possession.publicKey,
                    (ECPublicKey) gmx509Credentials.popEncPublicKey, sm2Credentials.popPublicKey);
        }
    }

    private static final
            class SM2KAKeyDerivation implements SSLKeyDerivation {
        private final HandshakeContext context;
        private final ECPrivateKey localPrivateKey;
        private final ECPublicKey localPublicKey;
        private final ECPrivateKey localTempPrivateKey;
        private final ECPublicKey localTempPublicKey;
        private final ECPublicKey peerPublicKey;
        private final ECPublicKey peerTempPublicKey;

        SM2KAKeyDerivation(HandshakeContext context,
                ECPrivateKey localPrivateKey, ECPublicKey localPublicKey,
                ECPrivateKey localTempPrivateKey, ECPublicKey localTempPublicKey,
                ECPublicKey peerPublicKey, ECPublicKey peerTempPublicKey) {
            this.context = context;
            this.localPrivateKey = localPrivateKey;
            this.localPublicKey = localPublicKey;
            this.localTempPrivateKey = localTempPrivateKey;
            this.localTempPublicKey = localTempPublicKey;
            this.peerPublicKey = peerPublicKey;
            this.peerTempPublicKey = peerTempPublicKey;
        }

        @Override
        public SecretKey deriveKey(String algorithm,
                AlgorithmParameterSpec params) throws IOException {
            return gmtlsDeriveKey(algorithm, params);
        }

        private SecretKey gmtlsDeriveKey(String algorithm,
                                       AlgorithmParameterSpec params) throws IOException {
            try {
                if (params == null) {
                    params = new SM2KeyExchangeParameterSpec(localPublicKey, localTempPrivateKey,
                            localTempPublicKey, peerTempPublicKey, 48, context.sslConfig.isClientMode);
                }
                KeyAgreement ka = JsseJce.getKeyAgreement("SM2");
                ka.init(localPrivateKey, params, null);
                ka.doPhase(peerPublicKey, true);
                SecretKey preMasterSecret =
                        ka.generateSecret("TlsPremasterSecret");

                SSLMasterKeyDerivation mskd =
                        SSLMasterKeyDerivation.valueOf(
                                context.negotiatedProtocol);
                if (mskd == null) {
                    // unlikely
                    throw new SSLHandshakeException(
                            "No expected master key derivation for protocol: " +
                            context.negotiatedProtocol.name);
                }
                SSLKeyDerivation kd = mskd.createKeyDerivation(
                        context, preMasterSecret);
                return kd.deriveKey("MasterSecret", params);
            } catch (GeneralSecurityException gse) {
                throw (SSLHandshakeException) new SSLHandshakeException(
                    "Could not generate secret").initCause(gse);
            }
        }

    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy