summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2017-08-01 14:30:06 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2017-08-07 14:51:16 +0200
commitf6cd10ad3c6d1e781832fc6c7a33f2413e3128bf (patch)
treee43a9ccc36cdf88ae3ca5deb9140d43c0dff4a4b
parent2f66cf08b1c98d692242655e54dbbbfca332b35d (diff)
downloadgnutls-f6cd10ad3c6d1e781832fc6c7a33f2413e3128bf.tar.gz
x509: store and read provable seed in PKCS#8 form of key
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
-rw-r--r--lib/x509/Makefile.am2
-rw-r--r--lib/x509/privkey.c1
-rw-r--r--lib/x509/privkey_pkcs8.c47
-rw-r--r--lib/x509/prov-seed.c135
-rw-r--r--lib/x509/prov-seed.h24
-rw-r--r--lib/x509/x509_int.h2
6 files changed, 201 insertions, 10 deletions
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 <random.h>
#include <pk.h>
#include <nettle/pbkdf2.h>
+#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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "gnutls_int.h"
+#include <datum.h>
+#include <global.h>
+#include "errors.h"
+#include <common.h>
+#include <x509.h>
+#include <x509_int.h>
+#include <mpi.h>
+#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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+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;