aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hal_internal.h12
-rw-r--r--rpc_client.c42
-rw-r--r--rpc_pkey.c8
-rw-r--r--rpc_serial.c15
4 files changed, 61 insertions, 16 deletions
diff --git a/hal_internal.h b/hal_internal.h
index 1c06494..5e08c4e 100644
--- a/hal_internal.h
+++ b/hal_internal.h
@@ -244,6 +244,18 @@ extern const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch, hal_rpc_remote
#define HAL_PKEY_HANDLE_PROXIMATE_FLAG (1 << 31)
/*
+ * Mostly used by the local_pkey code, but the mixed_pkey code needs
+ * it to pad hashes for RSA PKCS #1.5 signatures. This may indicate
+ * that we need a slightly more general internal API here, but not
+ * worth worrying about as long as we can treat RSA as a special case
+ * and just pass the plain hash for everything else.
+ */
+
+extern hal_error_t hal_rpc_pkey_pkcs1_construct_digestinfo(const hal_hash_handle_t handle,
+ uint8_t *digest_info, size_t *digest_info_len,
+ const size_t digest_info_max);
+
+/*
* Keystore API.
*
* The original design for this subsystem used two separate tables,
diff --git a/rpc_client.c b/rpc_client.c
index a517528..a952a6e 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -833,17 +833,30 @@ static hal_error_t pkey_mixed_sign(const hal_session_handle_t session,
signature, signature_len, signature_max);
hal_digest_algorithm_t alg;
+ hal_key_type_t pkey_type;
size_t digest_len;
hal_error_t err;
if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK ||
- (err = hal_rpc_hash_get_digest_length(alg, &digest_len)) != HAL_OK)
+ (err = hal_rpc_hash_get_digest_length(alg, &digest_len)) != HAL_OK ||
+ (err = hal_rpc_pkey_get_key_type(pkey, &pkey_type)) != HAL_OK)
return err;
- uint8_t digest[digest_len];
+ uint8_t digest[digest_len > signature_max ? digest_len : signature_max];
- if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
- return err;
+ switch (pkey_type) {
+
+ case HAL_KEY_TYPE_RSA_PRIVATE:
+ case HAL_KEY_TYPE_RSA_PUBLIC:
+ if ((err = hal_rpc_pkey_pkcs1_construct_digestinfo(hash, digest, &digest_len, sizeof(digest))) != HAL_OK)
+ return err;
+ break;
+
+ default:
+ if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
+ return err;
+
+ }
return mixed_handle_dispatch(pkey)->sign(session, pkey, hal_hash_handle_none, digest, digest_len,
signature, signature_len, signature_max);
@@ -860,17 +873,30 @@ static hal_error_t pkey_mixed_verify(const hal_session_handle_t session,
signature, signature_len);
hal_digest_algorithm_t alg;
+ hal_key_type_t pkey_type;
size_t digest_len;
hal_error_t err;
if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK ||
- (err = hal_rpc_hash_get_digest_length(alg, &digest_len)) != HAL_OK)
+ (err = hal_rpc_hash_get_digest_length(alg, &digest_len)) != HAL_OK ||
+ (err = hal_rpc_pkey_get_key_type(pkey, &pkey_type)) != HAL_OK)
return err;
- uint8_t digest[digest_len];
+ uint8_t digest[digest_len > signature_len ? digest_len : signature_len];
- if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
- return err;
+ switch (pkey_type) {
+
+ case HAL_KEY_TYPE_RSA_PRIVATE:
+ case HAL_KEY_TYPE_RSA_PUBLIC:
+ if ((err = hal_rpc_pkey_pkcs1_construct_digestinfo(hash, digest, &digest_len, sizeof(digest))) != HAL_OK)
+ return err;
+ break;
+
+ default:
+ if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
+ return err;
+
+ }
return mixed_handle_dispatch(pkey)->verify(session, pkey, hal_hash_handle_none,
digest, digest_len, signature, signature_len);
diff --git a/rpc_pkey.c b/rpc_pkey.c
index 6b548d5..d6efbe7 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -142,8 +142,8 @@ static inline pkey_slot_t *find_handle(const hal_pkey_handle_t handle)
* basic) ASN.1 encoding, which we perform inline.
*/
-static hal_error_t pkcs1_construct_digestinfo(const hal_hash_handle_t handle,
- uint8_t *digest_info, size_t *digest_info_len, const size_t digest_info_max)
+hal_error_t hal_rpc_pkey_pkcs1_construct_digestinfo(const hal_hash_handle_t handle,
+ uint8_t *digest_info, size_t *digest_info_len, const size_t digest_info_max)
{
assert(digest_info != NULL && digest_info_len != NULL);
@@ -623,7 +623,7 @@ static hal_error_t pkey_local_sign_rsa(uint8_t *keybuf, const size_t keybuf_len,
return HAL_ERROR_RESULT_TOO_LONG;
if (input == NULL) {
- if ((err = pkcs1_construct_digestinfo(hash, signature, &input_len, *signature_len)) != HAL_OK)
+ if ((err = hal_rpc_pkey_pkcs1_construct_digestinfo(hash, signature, &input_len, *signature_len)) != HAL_OK)
return err;
input = signature;
}
@@ -751,7 +751,7 @@ static hal_error_t pkey_local_verify_rsa(uint8_t *keybuf, const size_t keybuf_le
return err;
if (input == NULL) {
- if ((err = pkcs1_construct_digestinfo(hash, expected, &input_len, sizeof(expected))) != HAL_OK)
+ if ((err = hal_rpc_pkey_pkcs1_construct_digestinfo(hash, expected, &input_len, sizeof(expected))) != HAL_OK)
return err;
input = expected;
}
diff --git a/rpc_serial.c b/rpc_serial.c
index 728bbd8..0e0e6ff 100644
--- a/rpc_serial.c
+++ b/rpc_serial.c
@@ -35,6 +35,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/file.h>
#include <netinet/in.h>
#include <termios.h>
#include <unistd.h>
@@ -66,11 +67,17 @@ hal_error_t hal_serial_init(const char * const device, const uint32_t speed)
struct termios tty;
speed_t termios_speed;
+ /*
+ * Apparently Linux is too cool to need an atomic mechanism for
+ * locking an existing file, so we can't uses O_EXLOCK. Sigh.
+ */
+
fd = open(device, O_RDWR | O_NOCTTY | O_SYNC);
- if (fd == -1) {
- fprintf(stderr, "open %s: ", device);
- return perror(""), HAL_ERROR_RPC_TRANSPORT;
- }
+ if (fd == -1)
+ return perror(device), HAL_ERROR_RPC_TRANSPORT;
+
+ if (flock(fd, LOCK_EX) < 0)
+ return perror(device), HAL_ERROR_RPC_TRANSPORT;
if (tcgetattr (fd, &tty) != 0)
return perror("tcgetattr"), HAL_ERROR_RPC_TRANSPORT;