From f6cd10ad3c6d1e781832fc6c7a33f2413e3128bf Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 1 Aug 2017 14:30:06 +0200 Subject: x509: store and read provable seed in PKCS#8 form of key Signed-off-by: Nikos Mavrogiannopoulos --- lib/x509/Makefile.am | 2 + lib/x509/privkey.c | 1 - lib/x509/privkey_pkcs8.c | 47 +++++++++++++---- lib/x509/prov-seed.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++ lib/x509/prov-seed.h | 24 +++++++++ lib/x509/x509_int.h | 2 + 6 files changed, 201 insertions(+), 10 deletions(-) create mode 100644 lib/x509/prov-seed.c create mode 100644 lib/x509/prov-seed.h diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am index 2a775eacc7..d4d9cdae61 100644 --- a/lib/x509/Makefile.am +++ b/lib/x509/Makefile.am @@ -44,6 +44,8 @@ libgnutls_x509_la_SOURCES = \ dn.c \ attributes.c \ attributes.h \ + prov-seed.c \ + prov-seed.h \ extensions.c \ mpi.c \ output.c \ diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index 87de8087cc..81ff5c6db3 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -250,7 +250,6 @@ _gnutls_privkey_decode_pkcs1_rsa_key(const gnutls_datum_t * raw_key, gnutls_pk_params_clear(&pkey->params); gnutls_pk_params_release(&pkey->params); return NULL; - } /* Converts an ECC key to diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c index dea9a5482c..46351dca25 100644 --- a/lib/x509/privkey_pkcs8.c +++ b/lib/x509/privkey_pkcs8.c @@ -37,6 +37,8 @@ #include #include #include +#include "attributes.h" +#include "prov-seed.h" static int _decode_pkcs8_ecc_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey); @@ -217,13 +219,30 @@ encode_to_private_key_info(gnutls_x509_privkey_t pkey, goto error; } - /* Append an empty Attributes field. - */ - result = asn1_write_value(*pkey_info, "attributes", NULL, 0); - if (result != ASN1_SUCCESS) { - gnutls_assert(); - result = _gnutls_asn2err(result); - goto error; + if ((pkey->params.flags & GNUTLS_PK_FLAG_PROVABLE) && pkey->params.seed_size > 0) { + gnutls_datum_t seed_info; + + result = _x509_encode_provable_seed(pkey, &seed_info); + if (result < 0) { + gnutls_assert(); + goto error; + } + + result = _x509_set_attribute(*pkey_info, "attributes", OID_ATTR_PROV_SEED, &seed_info); + gnutls_free(seed_info.data); + if (result < 0) { + gnutls_assert(); + goto error; + } + } else { + /* Append an empty Attributes field. + */ + result = asn1_write_value(*pkey_info, "attributes", NULL, 0); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto error; + } } /* DER Encode the generated private key info. @@ -1173,6 +1192,8 @@ decode_private_key_info(const gnutls_datum_t * der, int result, len; char oid[MAX_OID_SIZE]; ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; + gnutls_datum_t sder; + int ret; if ((result = asn1_create_element(_gnutls_get_pkix(), @@ -1201,8 +1222,6 @@ decode_private_key_info(const gnutls_datum_t * der, result = _gnutls_asn2err(result); goto error; } - /* we only support RSA and DSA private keys. - */ pkey->params.algo = gnutls_oid_to_pk(oid); if (pkey->params.algo == GNUTLS_PK_UNKNOWN) { @@ -1243,6 +1262,16 @@ decode_private_key_info(const gnutls_datum_t * der, goto error; } + /* check for provable parameters attribute */ + ret = _x509_parse_attribute(pkcs8_asn, "attributes", OID_ATTR_PROV_SEED, 0, 1, &sder); + if (ret >= 0) { /* ignore it when not being present */ + ret = _x509_decode_provable_seed(pkey, &sder); + gnutls_free(sder.data); + if (ret < 0) { + gnutls_assert(); + } + } + result = 0; error: diff --git a/lib/x509/prov-seed.c b/lib/x509/prov-seed.c new file mode 100644 index 0000000000..b0f40c5802 --- /dev/null +++ b/lib/x509/prov-seed.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * 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 + * + */ + +#include "gnutls_int.h" +#include +#include +#include "errors.h" +#include +#include +#include +#include +#include "prov-seed.h" + +int _x509_encode_provable_seed(gnutls_x509_privkey_t pkey, gnutls_datum_t *der) +{ + + ASN1_TYPE c2; + int ret, result; + const char *oid; + + oid = gnutls_digest_get_oid(pkey->params.palgo); + if (oid == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if ((result = + asn1_create_element(_gnutls_get_gnutls_asn(), + "GNUTLS.ProvableSeed", + &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = asn1_write_value(c2, "seed", pkey->params.seed, pkey->params.seed_size); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + result = asn1_write_value(c2, "algorithm", oid, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + ret = _gnutls_x509_der_encode(c2, "", der, 0); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + + cleanup: + asn1_delete_structure2(&c2, ASN1_DELETE_FLAG_ZEROIZE); + return ret; +} + +int _x509_decode_provable_seed(gnutls_x509_privkey_t pkey, const gnutls_datum_t *der) +{ + + ASN1_TYPE c2; + int ret, result; + char oid[MAX_OID_SIZE]; + int oid_size; + gnutls_datum_t seed = {NULL, 0}; + + if ((result = + asn1_create_element(_gnutls_get_gnutls_asn(), + "GNUTLS.ProvableSeed", + &c2)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = _asn1_strict_der_decode(&c2, der->data, der->size, NULL); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + ret = _gnutls_x509_read_value(c2, "seed", &seed); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + if (seed.size <= sizeof(pkey->params.seed)) { + memcpy(pkey->params.seed, seed.data, seed.size); + pkey->params.seed_size = seed.size; + } else { + ret = 0; /* ignore struct */ + _gnutls_debug_log("%s: ignoring ProvableSeed due to very long params\n", __func__); + goto cleanup; + } + + oid_size = sizeof(oid); + result = asn1_read_value(c2, "algorithm", oid, &oid_size); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + ret = _gnutls_asn2err(result); + goto cleanup; + } + + pkey->params.palgo = gnutls_oid_to_digest(oid); + pkey->params.flags |= GNUTLS_PK_FLAG_PROVABLE; + + ret = 0; + + cleanup: + gnutls_free(seed.data); + asn1_delete_structure2(&c2, ASN1_DELETE_FLAG_ZEROIZE); + return ret; +} diff --git a/lib/x509/prov-seed.h b/lib/x509/prov-seed.h new file mode 100644 index 0000000000..55d6df0830 --- /dev/null +++ b/lib/x509/prov-seed.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * 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 + * + */ + +int _x509_encode_provable_seed(gnutls_x509_privkey_t pkey, gnutls_datum_t *der); +int _x509_decode_provable_seed(gnutls_x509_privkey_t pkey, const gnutls_datum_t *der); diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index e886ac1acd..e325c06bf2 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -49,6 +49,8 @@ #define HASH_OID_SHA3_384 "2.16.840.1.101.3.4.2.9" #define HASH_OID_SHA3_512 "2.16.840.1.101.3.4.2.10" +#define OID_ATTR_PROV_SEED "1.3.6.1.4.1.2312.18.8.1" + struct gnutls_x509_crl_iter { /* This is used to optimize reads by gnutls_x509_crl_iter_crt_serial() */ ASN1_TYPE rcache; -- cgit v1.2.1