diff options
-rw-r--r-- | hal_internal.h | 12 | ||||
-rw-r--r-- | rpc_client.c | 42 | ||||
-rw-r--r-- | rpc_pkey.c | 8 | ||||
-rw-r--r-- | rpc_serial.c | 15 |
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); @@ -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; |