summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2016-10-24 20:56:46 +0300
committerDmitry Eremin-Solenikov <dbaryshkov@gmail.com>2018-06-23 12:20:16 +0300
commitd2fde63f9d92acb61f77ce541000a58543e13ba5 (patch)
tree75d977eb0e7429e88760fefaf6ccee8c1d8aefe4
parent81e41559827570d2646e45f599fbb77a1310683c (diff)
downloadgnutls-d2fde63f9d92acb61f77ce541000a58543e13ba5.tar.gz
Support GOST private keys generation
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
-rw-r--r--lib/privkey.c16
-rw-r--r--lib/x509/privkey.c26
-rw-r--r--src/certtool-cfg.c2
-rw-r--r--src/certtool-common.c6
-rw-r--r--src/certtool.c16
-rw-r--r--tests/cert-tests/Makefile.am4
-rwxr-xr-xtests/cert-tests/gost103
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