diff options
author | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2016-10-24 20:56:46 +0300 |
---|---|---|
committer | Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> | 2018-06-23 12:20:16 +0300 |
commit | d2fde63f9d92acb61f77ce541000a58543e13ba5 (patch) | |
tree | 75d977eb0e7429e88760fefaf6ccee8c1d8aefe4 | |
parent | 81e41559827570d2646e45f599fbb77a1310683c (diff) | |
download | gnutls-d2fde63f9d92acb61f77ce541000a58543e13ba5.tar.gz |
Support GOST private keys generation
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r-- | lib/privkey.c | 16 | ||||
-rw-r--r-- | lib/x509/privkey.c | 26 | ||||
-rw-r--r-- | src/certtool-cfg.c | 2 | ||||
-rw-r--r-- | src/certtool-common.c | 6 | ||||
-rw-r--r-- | src/certtool.c | 16 | ||||
-rw-r--r-- | tests/cert-tests/Makefile.am | 4 | ||||
-rwxr-xr-x | tests/cert-tests/gost | 103 |
7 files changed, 169 insertions, 4 deletions
diff --git a/lib/privkey.c b/lib/privkey.c index e5b7e83965..ab2f2771b6 100644 --- a/lib/privkey.c +++ b/lib/privkey.c @@ -156,6 +156,7 @@ privkey_to_pubkey(gnutls_pk_algorithm_t pk, pub->algo = priv->algo; pub->pkflags = priv->pkflags; pub->curve = priv->curve; + pub->gost_params = priv->gost_params; pub->qbits = priv->qbits; memcpy(&pub->spki, &priv->spki, sizeof(gnutls_x509_spki_st)); @@ -209,6 +210,21 @@ privkey_to_pubkey(gnutls_pk_algorithm_t pk, return gnutls_assert_val(ret); break; + case GNUTLS_PK_GOST_01: + case GNUTLS_PK_GOST_12_256: + case GNUTLS_PK_GOST_12_512: + pub->params[GOST_X] = _gnutls_mpi_copy(priv->params[GOST_X]); + pub->params[GOST_Y] = _gnutls_mpi_copy(priv->params[GOST_Y]); + + pub->params_nr = GOST_PUBLIC_PARAMS; + + if (pub->params[GOST_X] == NULL || pub->params[GOST_Y] == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + break; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 83bb54c9aa..eea0b28b14 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1777,6 +1777,32 @@ gnutls_x509_privkey_generate2(gnutls_x509_privkey_t key, } } + if (IS_GOSTEC(algo)) { + unsigned params; + int size; + + if (algo == GNUTLS_PK_GOST_01) + params = GNUTLS_GOST_PARAMSET_CP_A; + else + params = GNUTLS_GOST_PARAMSET_TC26_Z; + + if (GNUTLS_BITS_ARE_CURVE(bits)) + bits = GNUTLS_BITS_TO_CURVE(bits); + else + bits = _gnutls_ecc_bits_to_curve(algo, bits); + + size = gnutls_ecc_curve_get_size(bits); + + if ((algo == GNUTLS_PK_GOST_01 && size != 32) || + (algo == GNUTLS_PK_GOST_12_256 && size != 32) || + (algo == GNUTLS_PK_GOST_12_512 && size != 64)) { + _gnutls_debug_log("curve is incompatible with public key algorithm\n"); + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + } + + key->params.gost_params = params; + } + if (flags & GNUTLS_PRIVKEY_FLAG_PROVABLE) { key->params.pkflags |= GNUTLS_PK_FLAG_PROVABLE; } diff --git a/src/certtool-cfg.c b/src/certtool-cfg.c index 4470911088..28ac3d5616 100644 --- a/src/certtool-cfg.c +++ b/src/certtool-cfg.c @@ -262,7 +262,7 @@ void cfg_init(void) { \ char str[512]; \ char * p; \ - int len; \ + size_t len; \ if (s_name == NULL) { \ i = 0; \ s_name = malloc(sizeof(char*)*MAX_ENTRIES); \ diff --git a/src/certtool-common.c b/src/certtool-common.c index 99b0e52a44..88a0f19535 100644 --- a/src/certtool-common.c +++ b/src/certtool-common.c @@ -1620,6 +1620,12 @@ gnutls_pk_algorithm_t figure_key_type(const char *key_type) return GNUTLS_PK_DSA; else if (strcasecmp(key_type, "ecdsa") == 0 || strcasecmp(key_type, "ecc") == 0) return GNUTLS_PK_ECDSA; + else if (strcasecmp(key_type, "gost01") == 0) + return GNUTLS_PK_GOST_01; + else if (strcasecmp(key_type, "gost12-256") == 0) + return GNUTLS_PK_GOST_12_256; + else if (strcasecmp(key_type, "gost12-512") == 0) + return GNUTLS_PK_GOST_12_512; else { fprintf(stderr, "unknown key type: %s\n", key_type); return GNUTLS_PK_UNKNOWN; diff --git a/src/certtool.c b/src/certtool.c index 5bac31f12c..13f36a60fa 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -149,7 +149,11 @@ generate_private_key_int(common_info_st * cinfo) bits = get_bits(key_type, cinfo->bits, cinfo->sec_param, 1); - if (key_type == GNUTLS_PK_ECDSA || key_type == GNUTLS_PK_EDDSA_ED25519) { + if (key_type == GNUTLS_PK_ECDSA || + key_type == GNUTLS_PK_EDDSA_ED25519 || + key_type == GNUTLS_PK_GOST_01 || + key_type == GNUTLS_PK_GOST_12_256 || + key_type == GNUTLS_PK_GOST_12_512) { char name[64]; int ecc_bits; @@ -541,7 +545,10 @@ generate_certificate(gnutls_privkey_t * ret_key, } if (!ca_status || server) { - if (pk == GNUTLS_PK_RSA) { /* DSA and ECDSA keys can only sign. */ + if (pk == GNUTLS_PK_RSA || + pk == GNUTLS_PK_GOST_01 || + pk == GNUTLS_PK_GOST_12_256 || + pk == GNUTLS_PK_GOST_12_512) { /* DSA and ECDSA keys can only sign. */ result = get_sign_status(server); if (result) usage |= @@ -1881,7 +1888,10 @@ void generate_request(common_info_st * cinfo) app_exit(1); } - if (pk == GNUTLS_PK_RSA) { + if (pk == GNUTLS_PK_RSA || + pk == GNUTLS_PK_GOST_01 || + pk == GNUTLS_PK_GOST_12_256 || + pk == GNUTLS_PK_GOST_12_512) { ret = get_sign_status(1); if (ret) usage |= GNUTLS_KEY_DIGITAL_SIGNATURE; diff --git a/tests/cert-tests/Makefile.am b/tests/cert-tests/Makefile.am index 96b6d087cd..14e30d893b 100644 --- a/tests/cert-tests/Makefile.am +++ b/tests/cert-tests/Makefile.am @@ -119,6 +119,10 @@ if ENABLE_DANE dist_check_SCRIPTS += dane endif +if ENABLE_GOST +dist_check_SCRIPTS += gost +endif + dist_check_SCRIPTS += certtool-rsa-pss certtool-eddsa TESTS = $(dist_check_SCRIPTS) diff --git a/tests/cert-tests/gost b/tests/cert-tests/gost new file mode 100755 index 0000000000..885c2fa5c7 --- /dev/null +++ b/tests/cert-tests/gost @@ -0,0 +1,103 @@ +#!/bin/sh + +# Copyright (C) 2016-2017 Free Software Foundation, Inc. +# +# Author: Dmitry Eremin-Solenikov +# +# This file is part of GnuTLS. +# +# The GnuTLS is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# as published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# This library 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +#set -e + +srcdir="${srcdir:-.}" +CERTTOOL="${CERTTOOL:-../../src/certtool${EXEEXT}}" +TMPFILE=gost.$$.tmp +TMPCA=gost-ca.$$.tmp +TMPCAKEY=gost-ca-key.$$.tmp +TMPSUBCA=gost-subca.$$.tmp +TMPSUBCAKEY=gost-subca-key.$$.tmp +TMPKEY=gost-key.$$.tmp +TMPTEMPL=template.$$.tmp +TMPUSER=user.$$.tmp +VERIFYOUT=verify.$$.tmp + +if ! test -x "${CERTTOOL}"; then + exit 77 +fi + +if test "${GNUTLS_FORCE_FIPS_MODE}" = 1;then + echo "Cannot run in FIPS140-2 mode" + exit 77 +fi + +echo ca > $TMPTEMPL +echo "cn = GOST STREEBOG 256 CA" >> $TMPTEMPL + +"${CERTTOOL}" --generate-privkey --key-type gost12-512 --curve TC26-512-A > $TMPCAKEY 2>/dev/null +#"${CERTTOOL}" --generate-privkey --key-type gost12-256 --curve CryptoPro-XchA > $TMPCAKEY 2>/dev/null + +"${CERTTOOL}" -d 2 --generate-self-signed --template $TMPTEMPL \ + --load-privkey $TMPCAKEY \ + --outfile $TMPCA \ + >$TMPFILE 2>&1 + +if [ $? != 0 ]; then + cat $TMPFILE + exit 1 +fi + +echo ca > $TMPTEMPL +"${CERTTOOL}" --generate-privkey --key-type gost12-256 --curve CryptoPro-A > $TMPSUBCAKEY 2>/dev/null +echo "cn = GOST STREEBOG-256 Mid CA" >> $TMPTEMPL + +"${CERTTOOL}" -d 2 --generate-certificate --template $TMPTEMPL \ + --load-ca-privkey $TMPCAKEY \ + --load-ca-certificate $TMPCA \ + --load-privkey $TMPSUBCAKEY \ + --outfile $TMPSUBCA \ + >$TMPFILE 2>&1 + +if [ $? != 0 ]; then + cat $TMPFILE + exit 1 +fi + +echo "cn = End-user" > $TMPTEMPL + +"${CERTTOOL}" --generate-privkey --key-type gost01 --curve CryptoPro-XchA > $TMPKEY 2>/dev/null + +"${CERTTOOL}" -d 2 --generate-certificate --template $TMPTEMPL \ + --load-ca-privkey $TMPSUBCAKEY \ + --load-ca-certificate $TMPSUBCA \ + --load-privkey $TMPKEY \ + --outfile $TMPUSER >$TMPFILE 2>&1 + +if [ $? != 0 ]; then + cat $TMPFILE + exit 1 +fi + +cat $TMPUSER $TMPSUBCA $TMPCA > $TMPFILE +"${CERTTOOL}" --verify-chain <$TMPFILE > $VERIFYOUT + +if [ $? != 0 ]; then + cat $VERIFYOUT + exit 1 +fi + +rm -f $VERIFYOUT $TMPUSER $TMPCA $TMPSUBCA $TMPTEMPL $TMPFILE +rm -f $TMPSUBCAKEY $TMPCAKEY $TMPKEY + +exit 0 |