aboutsummaryrefslogtreecommitdiff
path: root/rpc_pkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'rpc_pkey.c')
-rw-r--r--rpc_pkey.c227
1 files changed, 107 insertions, 120 deletions
diff --git a/rpc_pkey.c b/rpc_pkey.c
index e1521af..84e506d 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -3,8 +3,10 @@
* ----------
* Remote procedure call server-side public key implementation.
*
- * Authors: Rob Austein
- * Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ * Authors: Rob Austein, Paul Selkirk
+ * Copyright (c) 2015-2018, NORDUnet A/S All rights reserved.
+ * Copyright: 2019-2020, The Commons Conservancy Cryptech Project
+ * SPDX-License-Identifier: BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -16,9 +18,9 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * - Neither the name of the NORDUnet nor the names of its contributors may
- * be used to endorse or promote products derived from this software
- * without specific prior written permission.
+ * - Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
@@ -38,7 +40,6 @@
#include "hal.h"
#include "hal_internal.h"
#include "asn1_internal.h"
-#include "hashsig.h"
#ifndef HAL_STATIC_PKEY_STATE_BLOCKS
#define HAL_STATIC_PKEY_STATE_BLOCKS 0
@@ -530,12 +531,13 @@ static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client,
hal_pkey_handle_t *pkey,
hal_uuid_t *name,
const size_t hss_levels,
- const lms_algorithm_t lms_type,
- const lmots_algorithm_t lmots_type,
+ const hal_lms_algorithm_t lms_type,
+ const hal_lmots_algorithm_t lmots_type,
const hal_key_flags_t flags)
{
hal_assert(pkey != NULL && name != NULL);
+ uint8_t keybuf[hal_hashsig_key_t_size];
hal_hashsig_key_t *key = NULL;
hal_pkey_slot_t *slot;
hal_error_t err;
@@ -555,7 +557,7 @@ static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client,
slot->curve = HAL_CURVE_NONE;
slot->flags = flags;
- if ((err = hal_hashsig_key_gen(NULL, &key, hss_levels, lms_type, lmots_type)) != HAL_OK) {
+ if ((err = hal_hashsig_key_gen(NULL, &key, keybuf, sizeof(keybuf), hss_levels, lms_type, lmots_type, flags)) != HAL_OK) {
slot->type = HAL_KEY_TYPE_NONE;
return err;
}
@@ -566,11 +568,8 @@ static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client,
if ((err = hal_hashsig_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK)
err = hal_ks_store(ks_from_flags(flags), slot, der, der_len);
- /* There's nothing sensitive in the top-level private key, but we wipe
- * the der anyway, for symmetry with other key types. The actual key buf
- * is allocated internally and stays in memory, because everything else
- * is linked off of it.
- */
+ key = NULL;
+ memset(keybuf, 0, sizeof(keybuf));
memset(der, 0, sizeof(der));
if (err != HAL_OK) {
@@ -602,8 +601,6 @@ static hal_error_t pkey_local_close(const hal_pkey_handle_t pkey)
/*
* Delete a key from the store, given its key handle.
*/
-static hal_error_t pkey_local_get_key_type(const hal_pkey_handle_t pkey, hal_key_type_t *type);
-
static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey)
{
hal_pkey_slot_t *slot = find_handle(pkey);
@@ -616,20 +613,9 @@ static hal_error_t pkey_local_delete(const hal_pkey_handle_t pkey)
if ((err = check_writable(slot->client, slot->flags)) != HAL_OK)
return err;
- hal_key_type_t key_type;
- if ((err = pkey_local_get_key_type(pkey, &key_type)) != HAL_OK)
- return err;
-
- if (key_type == HAL_KEY_TYPE_HASHSIG_PRIVATE) {
- hal_hashsig_key_t *key;
- uint8_t keybuf[hal_hashsig_key_t_size];
- uint8_t der[HAL_KS_WRAPPED_KEYSIZE];
- size_t der_len;
- if ((err = ks_fetch_from_flags(slot, der, &der_len, sizeof(der))) != HAL_OK ||
- (err = hal_hashsig_private_key_from_der(&key, keybuf, sizeof(keybuf), der, der_len)) != HAL_OK ||
- (err = hal_hashsig_key_delete(key)) != HAL_OK)
- return err;
- }
+ if (slot->type == HAL_KEY_TYPE_HASHSIG_PRIVATE &&
+ (err = hal_hashsig_delete(&slot->name)) != HAL_OK)
+ return err;
err = hal_ks_delete(ks_from_flags(slot->flags), slot);
@@ -700,127 +686,98 @@ static hal_error_t pkey_local_get_key_flags(const hal_pkey_handle_t pkey,
}
/*
- * Get length of public key associated with handle.
+ * Get public key associated with handle.
*/
-static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey)
+static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey,
+ uint8_t *der, size_t *der_len, const size_t der_max)
{
hal_pkey_slot_t *slot = find_handle(pkey);
if (slot == NULL)
- return 0;
-
- size_t result = 0;
+ return HAL_ERROR_KEY_NOT_FOUND;
-#ifndef max
-#define max(a, b) ((a) >= (b) ? (a) : (b))
-#endif
- size_t keybuf_size = max(hal_rsa_key_t_size, hal_ecdsa_key_t_size);
- keybuf_size = max(keybuf_size, hal_hashsig_key_t_size);
- uint8_t keybuf[keybuf_size];
- hal_rsa_key_t *rsa_key = NULL;
- hal_ecdsa_key_t *ecdsa_key = NULL;
- hal_hashsig_key_t *hashsig_key = NULL;
- uint8_t der[HAL_KS_WRAPPED_KEYSIZE];
- size_t der_len;
+ uint8_t buf[HAL_KS_WRAPPED_KEYSIZE];
+ size_t buf_len;
hal_error_t err;
- if ((err = ks_fetch_from_flags(slot, der, &der_len, sizeof(der))) == HAL_OK) {
+ if ((err = ks_fetch_from_flags(slot, buf, &buf_len, sizeof(buf))) == HAL_OK) {
switch (slot->type) {
case HAL_KEY_TYPE_RSA_PUBLIC:
case HAL_KEY_TYPE_EC_PUBLIC:
case HAL_KEY_TYPE_HASHSIG_PUBLIC:
- result = der_len;
+ if (der_len != NULL)
+ *der_len = buf_len;
+ if (der != NULL) {
+ if (der_max < buf_len)
+ err = HAL_ERROR_RESULT_TOO_LONG;
+ else
+ memcpy(der, buf, buf_len);
+ }
break;
case HAL_KEY_TYPE_RSA_PRIVATE:
- if (hal_rsa_private_key_from_der(&rsa_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK)
- result = hal_rsa_public_key_to_der_len(rsa_key);
- break;
+ {
+ uint8_t keybuf[hal_rsa_key_t_size];
+ hal_rsa_key_t *key;
+ if ((err = hal_rsa_private_key_from_der(&key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
+ err = hal_rsa_public_key_to_der(key, der, der_len, der_max);
+ memset(keybuf, 0, sizeof(keybuf));
+ }
+ break;
case HAL_KEY_TYPE_EC_PRIVATE:
- if (hal_ecdsa_private_key_from_der(&ecdsa_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK)
- result = hal_ecdsa_public_key_to_der_len(ecdsa_key);
- break;
+ {
+ uint8_t keybuf[hal_ecdsa_key_t_size];
+ hal_ecdsa_key_t *key;
+ if ((err = hal_ecdsa_private_key_from_der(&key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
+ err = hal_ecdsa_public_key_to_der(key, der, der_len, der_max);
+ memset(keybuf, 0, sizeof(keybuf));
+ }
+ break;
case HAL_KEY_TYPE_HASHSIG_PRIVATE:
- if (hal_hashsig_private_key_from_der(&hashsig_key, keybuf, sizeof(keybuf), der, der_len) == HAL_OK)
- result = hal_hashsig_public_key_to_der_len(hashsig_key);
- break;
+ {
+ uint8_t keybuf[hal_hashsig_key_t_size];
+ hal_hashsig_key_t *key;
+ if ((err = hal_hashsig_private_key_from_der(&key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK) {
+ err = hal_hashsig_public_key_to_der(key, der, der_len, der_max);
+ key = NULL;
+ }
+ memset(keybuf, 0, sizeof(keybuf));
+ }
+ break;
default:
+ err = HAL_ERROR_UNSUPPORTED_KEY;
break;
}
}
- memset(keybuf, 0, sizeof(keybuf));
- memset(der, 0, sizeof(der));
+ memset(buf, 0, sizeof(buf));
- return result;
+ return err;
}
/*
- * Get public key associated with handle.
+ * Get length of public key associated with handle.
*/
-static hal_error_t pkey_local_get_public_key(const hal_pkey_handle_t pkey,
- uint8_t *der, size_t *der_len, const size_t der_max)
+static size_t pkey_local_get_public_key_len(const hal_pkey_handle_t pkey)
{
hal_pkey_slot_t *slot = find_handle(pkey);
if (slot == NULL)
- return HAL_ERROR_KEY_NOT_FOUND;
+ return 0;
- size_t keybuf_size = max(hal_rsa_key_t_size, hal_ecdsa_key_t_size);
- keybuf_size = max(keybuf_size, hal_hashsig_key_t_size);
- uint8_t keybuf[keybuf_size];
- hal_rsa_key_t *rsa_key = NULL;
- hal_ecdsa_key_t *ecdsa_key = NULL;
- hal_hashsig_key_t *hashsig_key = NULL;
- uint8_t buf[HAL_KS_WRAPPED_KEYSIZE];
- size_t buf_len;
+ size_t der_len;
hal_error_t err;
- if ((err = ks_fetch_from_flags(slot, buf, &buf_len, sizeof(buf))) == HAL_OK) {
- switch (slot->type) {
-
- case HAL_KEY_TYPE_RSA_PUBLIC:
- case HAL_KEY_TYPE_EC_PUBLIC:
- case HAL_KEY_TYPE_HASHSIG_PUBLIC:
- if (der_len != NULL)
- *der_len = buf_len;
- if (der != NULL && der_max < buf_len)
- err = HAL_ERROR_RESULT_TOO_LONG;
- else if (der != NULL)
- memcpy(der, buf, buf_len);
- break;
-
- case HAL_KEY_TYPE_RSA_PRIVATE:
- if ((err = hal_rsa_private_key_from_der(&rsa_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
- err = hal_rsa_public_key_to_der(rsa_key, der, der_len, der_max);
- break;
-
- case HAL_KEY_TYPE_EC_PRIVATE:
- if ((err = hal_ecdsa_private_key_from_der(&ecdsa_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
- err = hal_ecdsa_public_key_to_der(ecdsa_key, der, der_len, der_max);
- break;
-
- case HAL_KEY_TYPE_HASHSIG_PRIVATE:
- if ((err = hal_hashsig_private_key_from_der(&hashsig_key, keybuf, sizeof(keybuf), buf, buf_len)) == HAL_OK)
- err = hal_hashsig_public_key_to_der(hashsig_key, der, der_len, der_max);
- break;
-
- default:
- err = HAL_ERROR_UNSUPPORTED_KEY;
- break;
- }
- }
-
- memset(keybuf, 0, sizeof(keybuf));
- memset(buf, 0, sizeof(buf));
-
- return err;
+ if ((err = pkey_local_get_public_key(pkey, NULL, &der_len, 0)) == HAL_OK)
+ return der_len;
+ else
+ return 0;
}
/*
@@ -929,24 +886,28 @@ static hal_error_t pkey_local_sign_hashsig(hal_pkey_slot_t *slot,
if (input == NULL || input_len == 0) {
hal_digest_algorithm_t alg;
+ size_t digest_len;
if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK ||
- (err = hal_rpc_hash_get_digest_length(alg, &input_len)) != HAL_OK)
+ (err = hal_rpc_hash_get_digest_length(alg, &digest_len)) != HAL_OK)
return err;
- if (input_len > signature_max)
+ if (digest_len > signature_max)
return HAL_ERROR_RESULT_TOO_LONG;
- if ((err = hal_rpc_hash_finalize(hash, signature, input_len)) != HAL_OK)
+ uint8_t digest[digest_len];
+
+ if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
return err;
- input = signature;
+ err = hal_hashsig_sign(NULL, key, digest, digest_len, signature, signature_len, signature_max);
}
- if ((err = hal_hashsig_sign(NULL, key, input, input_len, signature, signature_len, signature_max)) != HAL_OK)
- return err;
+ else
+ err = hal_hashsig_sign(NULL, key, input, input_len, signature, signature_len, signature_max);
- return HAL_OK;
+ key = NULL;
+ return err;
}
static hal_error_t pkey_local_sign(const hal_pkey_handle_t pkey,
@@ -1113,13 +1074,23 @@ static hal_error_t pkey_local_verify_hashsig(uint8_t *keybuf, const size_t keybu
hal_assert(signature != NULL && signature_len > 0);
hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0));
- if ((err = hal_hashsig_public_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ switch (type) {
+ case HAL_KEY_TYPE_HASHSIG_PRIVATE:
+ err = hal_hashsig_private_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ break;
+ case HAL_KEY_TYPE_HASHSIG_PUBLIC:
+ err = hal_hashsig_public_key_from_der(&key, keybuf, keybuf_len, der, der_len);
+ break;
+ default:
+ err = HAL_ERROR_IMPOSSIBLE;
+ }
+
+ if (err != HAL_OK)
return err;
if (input == NULL || input_len == 0) {
hal_digest_algorithm_t alg;
- // ???
if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK ||
(err = hal_rpc_hash_get_digest_length(alg, &input_len)) != HAL_OK ||
(err = hal_rpc_hash_finalize(hash, digest, sizeof(digest))) != HAL_OK)
@@ -1162,6 +1133,7 @@ static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey,
verifier = pkey_local_verify_ecdsa;
keybuf_size = hal_ecdsa_key_t_size;
break;
+ case HAL_KEY_TYPE_HASHSIG_PRIVATE:
case HAL_KEY_TYPE_HASHSIG_PUBLIC:
verifier = pkey_local_verify_hashsig;
keybuf_size = hal_hashsig_key_t_size;
@@ -1255,6 +1227,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client,
case MATCH_STATE_START:
prev = uuid_zero;
++*state;
+ /* fall through */
case MATCH_STATE_TOKEN:
if (((mask & HAL_KEY_FLAG_TOKEN) == 0 || (mask & flags & HAL_KEY_FLAG_TOKEN) != 0) &&
@@ -1266,6 +1239,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client,
return HAL_OK;
prev = uuid_zero;
++*state;
+ /* fall through */
case MATCH_STATE_VOLATILE:
if (((mask & HAL_KEY_FLAG_TOKEN) == 0 || (mask & flags & HAL_KEY_FLAG_TOKEN) == 0) &&
@@ -1276,6 +1250,7 @@ static hal_error_t pkey_local_match(const hal_client_handle_t client,
if (*result_len == result_max)
return HAL_OK;
++*state;
+ /* fall through */
case MATCH_STATE_DONE:
return HAL_OK;
@@ -1374,6 +1349,11 @@ static hal_error_t pkey_local_export(const hal_pkey_handle_t pkey_handle,
if ((err = ks_fetch_from_flags(pkey, pkcs8, &len, pkcs8_max)) != HAL_OK)
goto fail;
+ /* hashsig export partitions the keyspace, so needs to update the stored key */
+ if (pkey->type == HAL_KEY_TYPE_HASHSIG_PRIVATE &&
+ (err = hal_hashsig_export(&pkey->name, pkcs8, &len, pkcs8_max)) != HAL_OK)
+ goto fail;
+
if ((err = hal_get_random(NULL, kek, KEK_LENGTH)) != HAL_OK)
goto fail;
@@ -1483,6 +1463,13 @@ static hal_error_t pkey_local_import(const hal_client_handle_t client,
if ((err = hal_aes_keyunwrap(NULL, kek, sizeof(kek), data, data_len, der, &der_len)) != HAL_OK)
goto fail;
+ hal_key_type_t type;
+ hal_curve_name_t curve;
+ if ((err = hal_asn1_guess_key_type(&type, &curve, der, der_len)) == HAL_OK &&
+ type == HAL_KEY_TYPE_HASHSIG_PRIVATE &&
+ (err = hal_hashsig_import(der, der_len, flags)) != HAL_OK)
+ goto fail;
+
err = hal_rpc_pkey_load(client, session, pkey, name, der, der_len, flags);
fail: