summaryrefslogtreecommitdiffstats
path: root/lib/x509/prov-seed.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lib/x509/prov-seed.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/lib/x509/prov-seed.c b/lib/x509/prov-seed.c
new file mode 100644
index 0000000..d0119b4
--- /dev/null
+++ b/lib/x509/prov-seed.c
@@ -0,0 +1,141 @@
+/*
+ * 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 <https://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"
+
+/* This function encodes a seed value and a hash algorithm OID to the format
+ * described in RFC8479. The output is the DER encoded form.
+ */
+int _x509_encode_provable_seed(gnutls_x509_privkey_t pkey, gnutls_datum_t *der)
+{
+
+ asn1_node 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;
+}
+
+/* This function decodes a DER encoded form of seed and a hash algorithm, as in
+ * RFC8479.
+ */
+int _x509_decode_provable_seed(gnutls_x509_privkey_t pkey, const gnutls_datum_t *der)
+{
+
+ asn1_node 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.pkflags |= GNUTLS_PK_FLAG_PROVABLE;
+
+ ret = 0;
+
+ cleanup:
+ gnutls_free(seed.data);
+ asn1_delete_structure2(&c2, ASN1_DELETE_FLAG_ZEROIZE);
+ return ret;
+}