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

org.openeuler.gm.GMTlsUtil Maven / Gradle / Ivy

There is a newer version: 1.1.3
Show newest version
/*
 * Copyright (c) 2005, 2017, 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.gm;

import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration;

/**
 * GM TLS util
 */
public class GMTlsUtil {
    private final static byte[] B0 = new byte[0];

    final static byte[] LABEL_MASTER_SECRET = // "master secret"
            {109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116};

    final static byte[] LABEL_EXTENDED_MASTER_SECRET =
            // "extended master secret"
            {101, 120, 116, 101, 110, 100, 101, 100, 32, 109, 97, 115, 116,
                    101, 114, 32, 115, 101, 99, 114, 101, 116};

    final static byte[] LABEL_KEY_EXPANSION = // "key expansion"
            {107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110};

    final static byte[] LABEL_CLIENT_WRITE_KEY = // "client write key"
            {99, 108, 105, 101, 110, 116, 32, 119, 114, 105, 116, 101, 32,
                    107, 101, 121};

    final static byte[] LABEL_SERVER_WRITE_KEY = // "server write key"
            {115, 101, 114, 118, 101, 114, 32, 119, 114, 105, 116, 101, 32,
                    107, 101, 121};

    final static byte[] LABEL_IV_BLOCK = // "IV block"
            {73, 86, 32, 98, 108, 111, 99, 107};

    /*
     * TLS HMAC "inner" and "outer" padding.  This isn't a function
     * of the digest algorithm.
     */
    private static final byte[] HMAC_ipad64 = genPad((byte) 0x36, 64);
    private static final byte[] HMAC_ipad128 = genPad((byte) 0x36, 128);
    private static final byte[] HMAC_opad64 = genPad((byte) 0x5c, 64);
    private static final byte[] HMAC_opad128 = genPad((byte) 0x5c, 128);

    static byte[] genPad(byte b, int count) {
        byte[] padding = new byte[count];
        Arrays.fill(padding, b);
        return padding;
    }

    static byte[] concat(byte[] b1, byte[] b2) {
        int n1 = b1.length;
        int n2 = b2.length;
        byte[] b = new byte[n1 + n2];
        System.arraycopy(b1, 0, b, 0, n1);
        System.arraycopy(b2, 0, b, n1, n2);
        return b;
    }

    static byte[] doGMTLS11PRF(byte[] secret, byte[] labelBytes,
                               byte[] seed, int outputLength,
                               String prfHash, int prfHashLength, int prfBlockSize)
            throws NoSuchAlgorithmException, DigestException {
        if (prfHash == null) {
            throw new NoSuchAlgorithmException("Unspecified PRF algorithm");
        }
        MessageDigest prfMD = MessageDigest.getInstance(prfHash);
        return doGMTLS11PRF(secret, labelBytes, seed, outputLength,
                prfMD, prfHashLength, prfBlockSize);
    }

    static byte[] doGMTLS11PRF(byte[] secret, byte[] labelBytes,
                               byte[] seed, int outputLength,
                               MessageDigest mdPRF, int mdPRFLen, int mdPRFBlockSize)
            throws DigestException {

        if (secret == null) {
            secret = B0;
        }

        // If we have a long secret, digest it first.
        if (secret.length > mdPRFBlockSize) {
            secret = mdPRF.digest(secret);
        }

        byte[] output = new byte[outputLength];
        byte[] ipad;
        byte[] opad;

        switch (mdPRFBlockSize) {
            case 64:
                ipad = HMAC_ipad64.clone();
                opad = HMAC_opad64.clone();
                break;
            case 128:
                ipad = HMAC_ipad128.clone();
                opad = HMAC_opad128.clone();
                break;
            default:
                throw new DigestException("Unexpected block size.");
        }

        // P_HASH(Secret, label + seed)
        expand(mdPRF, mdPRFLen, secret, 0, secret.length, labelBytes,
                seed, output, ipad, opad);

        return output;
    }

    /*
     * @param digest the MessageDigest to produce the HMAC
     * @param hmacSize the HMAC size
     * @param secret the secret
     * @param secOff the offset into the secret
     * @param secLen the secret length
     * @param label the label
     * @param seed the seed
     * @param output the output array
     */
    private static void expand(MessageDigest digest, int hmacSize,
                               byte[] secret, int secOff, int secLen, byte[] label, byte[] seed,
                               byte[] output, byte[] pad1, byte[] pad2) throws DigestException {
        /*
         * modify the padding used, by XORing the key into our copy of that
         * padding.  That's to avoid doing that for each HMAC computation.
         */
        for (int i = 0; i < secLen; i++) {
            pad1[i] ^= secret[i + secOff];
            pad2[i] ^= secret[i + secOff];
        }

        byte[] tmp = new byte[hmacSize];
        byte[] aBytes = null;

        /*
         * compute:
         *
         *     P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
         *                            HMAC_hash(secret, A(2) + seed) +
         *                            HMAC_hash(secret, A(3) + seed) + ...
         * A() is defined as:
         *
         *     A(0) = seed
         *     A(i) = HMAC_hash(secret, A(i-1))
         */
        int remaining = output.length;
        int ofs = 0;
        while (remaining > 0) {
            /*
             * compute A() ...
             */
            // inner digest
            digest.update(pad1);
            if (aBytes == null) {
                digest.update(label);
                digest.update(seed);
            } else {
                digest.update(aBytes);
            }
            digest.digest(tmp, 0, hmacSize);

            // outer digest
            digest.update(pad2);
            digest.update(tmp);
            if (aBytes == null) {
                aBytes = new byte[hmacSize];
            }
            digest.digest(aBytes, 0, hmacSize);

            /*
             * compute HMAC_hash() ...
             */
            // inner digest
            digest.update(pad1);
            digest.update(aBytes);
            digest.update(label);
            digest.update(seed);
            digest.digest(tmp, 0, hmacSize);

            // outer digest
            digest.update(pad2);
            digest.update(tmp);
            digest.digest(tmp, 0, hmacSize);

            int k = Math.min(hmacSize, remaining);
            for (int i = 0; i < k; i++) {
                output[ofs++] ^= tmp[i];
            }
            remaining -= k;
        }
    }

    /*
     * Determine whether it is an invalid EC certificate.
     */
    public static boolean isInvalidECCert(String keyType, String sigAlgName) {
        // If the keyType is EC, filter the certificate of the signature algorithm SM3withSM2.
        return keyType.equals(GMConstants.EC) && GMConstants.equalsAlgorithm(
                GMConstants.SM3_WITH_SM2, sigAlgName);
    }

    /*
     * Determine whether it is an invalid SM2 certificate.
     */
    public static boolean isInvalidSM2Cert(String keyType, String sigAlgName) {
        return keyType.equals(GMConstants.SM2) && !GMConstants.equalsAlgorithm(
                GMConstants.SM3_WITH_SM2, sigAlgName);
    }

    /*
     * Determine whether it is an invalid EC or SM2 certificate.
     */
    public static boolean isInvalidECOrSM2Cert(String keyType, String sigAlgName) {
        return isInvalidECCert(keyType, sigAlgName) || isInvalidSM2Cert(keyType, sigAlgName);
    }

    /**
     * Copy source keystore to dest keystore.
     * @param srcKeyStore Source keystore
     * @param srcStorePassword Source keystore password
     * @param destKeyStore Dest keystore
     * @param destStorePassword  Dest keystore password
     */
    public static void copyKeyStore(KeyStore srcKeyStore, char[] srcStorePassword,
                                     KeyStore destKeyStore , char[] destStorePassword)
            throws KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException {
        for (Enumeration e = srcKeyStore.aliases(); e.hasMoreElements(); ) {
            String alias = e.nextElement();
            if (srcKeyStore.isCertificateEntry(alias)) {
                Certificate cert = srcKeyStore.getCertificate(alias);
                if (cert instanceof X509Certificate) {
                    destKeyStore.setCertificateEntry(alias, cert);
                }
            } else if (srcKeyStore.isKeyEntry(alias)) {
                Certificate[] certs = srcKeyStore.getCertificateChain(alias);
                if ((certs != null) && (certs.length > 0) &&
                        (certs[0] instanceof X509Certificate)) {
                    Key key = srcKeyStore.getKey(alias, srcStorePassword);
                    destKeyStore.setKeyEntry(alias, key, destStorePassword, certs);
                }
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy