Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
yubihsm.c File Reference
#include <yubihsm.h>
#include "internal.h"
#include <arpa/inet.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <limits.h>
#include "../common/rand.h"
#include "../common/pkcs5.h"
#include "../common/hash.h"
#include "../aes_cmac/aes_cmac.h"
#include "debug_lib.h"
#include "../common/insecure_memzero.h"
Include dependency graph for yubihsm.c:

Go to the source code of this file.

Macros

#define STATIC_USB_BACKEND   "usb"
 
#define STATIC_HTTP_BACKEND   "http"
 
#define LIST_SEPARATORS   ":,;|"
 
#define LIST_ID   1
 
#define LIST_TYPE   2
 
#define LIST_DOMAINS   3
 
#define LIST_CAPABILITIES   4
 
#define LIST_ALGORITHM   5
 
#define LIST_LABEL   6
 
#define STATUS_ENDPOINT   "/connector/status"
 
#define API_ENDPOINT   "/connector/api"
 
#define USB_LIB   "libyubihsm_usb.so." SOVERSION
 
#define HTTP_LIB   "libyubihsm_http.so." SOVERSION
 
#define htonll(x)
 

Functions

yh_rc yh_send_plain_msg (yh_connector *connector, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len)
 
yh_rc yh_send_secure_msg (yh_session *session, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len)
 
yh_rc yh_create_session_derived (yh_connector *connector, uint16_t authkey_id, const uint8_t *password, size_t password_len, bool recreate, yh_session **session)
 
yh_rc yh_create_session (yh_connector *connector, uint16_t authkey_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate, yh_session **session)
 
yh_rc yh_begin_create_session_ext (yh_connector *connector, uint16_t authkey_id, uint8_t **context, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session)
 
yh_rc yh_finish_create_session_ext (yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram, size_t card_cryptogram_len)
 
yh_rc yh_destroy_session (yh_session **session)
 
bool yh_connector_has_device (yh_connector *connector)
 
yh_rc yh_get_connector_version (yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch)
 
yh_rc yh_get_connector_address (yh_connector *connector, char **const address)
 
yh_rc yh_util_get_device_info (yh_connector *connector, uint8_t *major, uint8_t *minor, uint8_t *patch, uint32_t *serial, uint8_t *log_total, uint8_t *log_used, yh_algorithm *algorithms, size_t *n_algorithms)
 
yh_rc yh_util_list_objects (yh_session *session, uint16_t id, yh_object_type type, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const char *label, yh_object_descriptor *objects, size_t *n_objects)
 
yh_rc yh_util_get_object_info (yh_session *session, uint16_t id, yh_object_type type, yh_object_descriptor *object)
 
yh_rc yh_util_get_public_key (yh_session *session, uint16_t id, uint8_t *data, size_t *data_len, yh_algorithm *algorithm)
 
yh_rc yh_util_close_session (yh_session *session)
 
yh_rc yh_util_sign_pkcs1v1_5 (yh_session *session, uint16_t key_id, bool hashed, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_sign_pss (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len, size_t salt_len, yh_algorithm mgf1Algo)
 
yh_rc yh_util_sign_ecdsa (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_sign_eddsa (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_sign_hmac (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_get_pseudo_random (yh_session *session, size_t len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_import_rsa_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *p, const uint8_t *q)
 
yh_rc yh_util_import_ec_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *s)
 
yh_rc yh_util_import_ed_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *k)
 
yh_rc yh_util_import_hmac_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *key, size_t key_len)
 
yh_rc yh_util_generate_rsa_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
 
yh_rc yh_util_generate_ec_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
 
yh_rc yh_util_generate_ed_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
 
yh_rc yh_util_verify_hmac (yh_session *session, uint16_t key_id, const uint8_t *signature, size_t signature_len, const uint8_t *data, size_t data_len, bool *verified)
 
yh_rc yh_util_generate_hmac_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm)
 
yh_rc yh_util_decrypt_pkcs1v1_5 (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_decrypt_oaep (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len, const uint8_t *label, size_t label_len, yh_algorithm mgf1Algo)
 
yh_rc yh_util_derive_ecdh (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_delete_object (yh_session *session, uint16_t id, yh_object_type type)
 
yh_rc yh_util_export_wrapped (yh_session *session, uint16_t wrapping_key_id, yh_object_type target_type, uint16_t target_id, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_import_wrapped (yh_session *session, uint16_t wrapping_key_id, const uint8_t *in, size_t in_len, yh_object_type *target_type, uint16_t *target_id)
 
yh_rc yh_util_import_wrap_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities, const uint8_t *in, size_t in_len)
 
yh_rc yh_util_generate_wrap_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const yh_capabilities *delegated_capabilities)
 
yh_rc yh_util_get_log_entries (yh_session *session, uint16_t *unlogged_boot, uint16_t *unlogged_auth, yh_log_entry *out, size_t *n_items)
 
yh_rc yh_util_set_log_index (yh_session *session, uint16_t index)
 
yh_rc yh_util_get_opaque (yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_import_opaque (yh_session *session, uint16_t *object_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *in, size_t in_len)
 
yh_rc yh_util_sign_ssh_certificate (yh_session *session, uint16_t key_id, uint16_t template_id, yh_algorithm sig_algo, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_get_template (yh_session *session, uint16_t object_id, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_import_template (yh_session *session, uint16_t *object_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, const uint8_t *in, size_t in_len)
 
yh_rc yh_get_session_id (yh_session *session, uint8_t *sid)
 
yh_rc yh_authenticate_session (yh_session *session)
 
yh_rc yh_util_import_authentication_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)
 
yh_rc yh_util_import_authentication_key_derived (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *password, size_t password_len)
 
yh_rc yh_util_change_authentication_key (yh_session *session, uint16_t *key_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)
 
yh_rc yh_util_change_authentication_key_derived (yh_session *session, uint16_t *key_id, const uint8_t *password, size_t password_len)
 
yh_rc yh_util_create_otp_aead (yh_session *session, uint16_t key_id, const uint8_t *key, const uint8_t *private_id, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_randomize_otp_aead (yh_session *session, uint16_t key_id, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_decrypt_otp (yh_session *session, uint16_t key_id, const uint8_t *aead, size_t aead_len, const uint8_t *otp, uint16_t *useCtr, uint8_t *sessionCtr, uint8_t *tstph, uint16_t *tstpl)
 
yh_rc yh_util_import_otp_aead_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, uint32_t nonce_id, const uint8_t *in, size_t in_len)
 
yh_rc yh_util_generate_otp_aead_key (yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, yh_algorithm algorithm, uint32_t nonce_id)
 
yh_rc yh_util_sign_attestation_certificate (yh_session *session, uint16_t key_id, uint16_t attest_id, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_set_option (yh_session *session, yh_option option, size_t len, uint8_t *val)
 
yh_rc yh_util_get_option (yh_session *session, yh_option option, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_get_storage_info (yh_session *session, uint16_t *total_records, uint16_t *free_records, uint16_t *total_pages, uint16_t *free_pages, uint16_t *page_size)
 
yh_rc yh_util_wrap_data (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_unwrap_data (yh_session *session, uint16_t key_id, const uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
 
yh_rc yh_util_blink_device (yh_session *session, uint8_t seconds)
 
yh_rc yh_util_reset_device (yh_session *session)
 
yh_rc yh_set_verbosity (yh_connector *connector, uint8_t verbosity)
 
yh_rc yh_get_verbosity (uint8_t *verbosity)
 
void yh_set_debug_output (yh_connector *connector, FILE *output)
 
yh_rc yh_init (void)
 
yh_rc yh_exit (void)
 
yh_rc yh_init_connector (const char *url, yh_connector **connector)
 
yh_rc yh_set_connector_option (yh_connector *connector, yh_connector_option opt, const void *val)
 
yh_rc yh_connect (yh_connector *connector, int timeout)
 
yh_rc yh_disconnect (yh_connector *connector)
 
yh_rc yh_string_to_capabilities (const char *capability, yh_capabilities *result)
 
yh_rc yh_capabilities_to_strings (const yh_capabilities *num, const char *result[], size_t *n_result)
 
bool yh_check_capability (const yh_capabilities *capabilities, const char *capability)
 
yh_rc yh_merge_capabilities (const yh_capabilities *a, const yh_capabilities *b, yh_capabilities *result)
 
yh_rc yh_filter_capabilities (const yh_capabilities *capabilities, const yh_capabilities *filter, yh_capabilities *result)
 
bool yh_is_rsa (yh_algorithm algorithm)
 
bool yh_is_ec (yh_algorithm algorithm)
 
bool yh_is_ed (yh_algorithm algorithm)
 
bool yh_is_hmac (yh_algorithm algorithm)
 
yh_rc yh_get_key_bitlength (yh_algorithm algorithm, size_t *result)
 
yh_rc yh_algo_to_string (yh_algorithm algo, char const **result)
 
yh_rc yh_string_to_algo (const char *string, yh_algorithm *algo)
 
yh_rc yh_type_to_string (yh_object_type type, char const **result)
 
yh_rc yh_string_to_type (const char *string, yh_object_type *type)
 
yh_rc yh_string_to_option (const char *string, yh_option *option)
 
bool yh_verify_logs (yh_log_entry *logs, size_t n_items, yh_log_entry *last_previous_log)
 
yh_rc yh_string_to_domains (const char *domains, uint16_t *result)
 
yh_rc yh_domains_to_string (uint16_t domains, char *string, size_t max_len)
 

Variables

uint8_t _yh_verbosity YH_INTERNAL = 0
 

Macro Definition Documentation

◆ API_ENDPOINT

#define API_ENDPOINT   "/connector/api"

Definition at line 3913 of file yubihsm.c.

◆ htonll

#define htonll ( x)
Value:
((1 == htonl(1)) \
? (x) \
: ((uint64_t) htonl((x) &0xFFFFFFFF) << 32) | htonl((x) >> 32))
unsigned __int64 uint64_t
Definition stdint.h:136

Definition at line 4110 of file yubihsm.c.

4110#define htonll(x) \
4111 ((1 == htonl(1)) \
4112 ? (x) \
4113 : ((uint64_t) htonl((x) &0xFFFFFFFF) << 32) | htonl((x) >> 32))

◆ HTTP_LIB

#define HTTP_LIB   "libyubihsm_http.so." SOVERSION

◆ LIST_ALGORITHM

#define LIST_ALGORITHM   5

Definition at line 1027 of file yubihsm.c.

◆ LIST_CAPABILITIES

#define LIST_CAPABILITIES   4

Definition at line 1026 of file yubihsm.c.

◆ LIST_DOMAINS

#define LIST_DOMAINS   3

Definition at line 1025 of file yubihsm.c.

◆ LIST_ID

#define LIST_ID   1

Definition at line 1023 of file yubihsm.c.

◆ LIST_LABEL

#define LIST_LABEL   6

Definition at line 1028 of file yubihsm.c.

◆ LIST_SEPARATORS

#define LIST_SEPARATORS   ":,;|"

Definition at line 55 of file yubihsm.c.

◆ LIST_TYPE

#define LIST_TYPE   2

Definition at line 1024 of file yubihsm.c.

◆ STATIC_HTTP_BACKEND

#define STATIC_HTTP_BACKEND   "http"

Definition at line 44 of file yubihsm.c.

◆ STATIC_USB_BACKEND

#define STATIC_USB_BACKEND   "usb"

Definition at line 43 of file yubihsm.c.

◆ STATUS_ENDPOINT

#define STATUS_ENDPOINT   "/connector/status"

Definition at line 3912 of file yubihsm.c.

◆ USB_LIB

#define USB_LIB   "libyubihsm_usb.so." SOVERSION

Function Documentation

◆ yh_algo_to_string()

yh_rc yh_algo_to_string ( yh_algorithm algo,
char const ** result )

Convert an algorithm to its string representation.

Parameters
algoAlgorithm to convert. See yh_algorithm
resultThe algorithm as a String. "Unknown" if the algorithm is not supported by YubiHSM 2.
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if result is NULL.
See also
Algorithms

Definition at line 4384 of file yubihsm.c.

4384 {
4385
4386 if (result == NULL) {
4389 }
4390
4391 for (size_t i = 0; i < sizeof(yh_algorithms) / sizeof(yh_algorithms[0]);
4392 i++) {
4393 if (algo == yh_algorithms[i].algorithm) {
4394 *result = yh_algorithms[i].name;
4395 return YHR_SUCCESS;
4396 }
4397 }
4398
4399 *result = "Unknown";
4400 return YHR_SUCCESS;
4401}
#define DBG_ERR(...)
Definition debug_lib.h:76
const char * yh_strerror(yh_rc err)
Definition error.c:65
yh_algorithm algorithm
Definition yubihsm.h:619
@ YHR_SUCCESS
Returned value when function was successful.
Definition yubihsm.h:172
@ YHR_INVALID_PARAMETERS
Returned value when an argument to a function is invalid.
Definition yubihsm.h:182
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_authenticate_session()

yh_rc yh_authenticate_session ( yh_session * session)

Authenticate session

Parameters
sessionSession to authenticate
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. YHR_SESSION_AUTHENTICATION_FAILED if the session fails to authenticate. See yh_rc for other possible errors
See also
Session

Definition at line 2927 of file yubihsm.c.

2927 {
2928
2929 Msg msg;
2930 Msg response_msg;
2931 yh_rc yrc;
2932
2933 uint8_t mac_buf[64];
2934 uint16_t mac_buf_len;
2935
2936 if (session == NULL) {
2939 }
2940
2941 // Send AUTHENTICATE SESSION command
2942 msg.st.cmd = YHC_AUTHENTICATE_SESSION;
2943 msg.st.len = 1 + SCP_HOST_CRYPTO_LEN + SCP_MAC_LEN;
2944
2945 msg.st.data[0] = session->s.sid;
2946
2947 // Compute host cryptogram
2948 yrc = compute_host_cryptogram(session, msg.st.data + 1);
2949 if (yrc != YHR_SUCCESS) {
2950 DBG_ERR("%s", yh_strerror(yrc));
2951 return yrc;
2952 }
2953
2954 DBG_INT(msg.st.data + 1, SCP_HOST_CRYPTO_LEN, "Host cryptogram: ");
2955
2956 mac_buf_len = SCP_PRF_LEN + msg.st.len + 3 - SCP_MAC_LEN;
2957 memset(mac_buf, 0, SCP_PRF_LEN); // Initial mac chaining value
2958 msg.st.len = htons(msg.st.len);
2959 memcpy(mac_buf + SCP_PRF_LEN, msg.raw, mac_buf_len);
2960 msg.st.len = ntohs(msg.st.len);
2961
2962 compute_full_mac(mac_buf, mac_buf_len, session->s.s_mac, SCP_KEY_LEN,
2963 session->s.mac_chaining_value);
2964 memcpy(msg.st.data + 1 + SCP_HOST_CRYPTO_LEN, session->s.mac_chaining_value,
2965 SCP_MAC_LEN);
2966
2967 // Reset counter to 1
2968 memset(session->s.ctr, 0, SCP_PRF_LEN);
2969 session->s.ctr[SCP_PRF_LEN - 1]++;
2970
2971 yrc = send_msg(session->parent, &msg, &response_msg);
2972 if (yrc != YHR_SUCCESS) {
2973 DBG_ERR("%s", yh_strerror(yrc));
2974 return yrc;
2975 }
2976
2977 if (response_msg.st.cmd != YHC_AUTHENTICATE_SESSION_R) {
2978 DBG_ERR("%s", yh_strerror(yrc));
2980 }
2981
2982 return YHR_SUCCESS;
2983}
#define DBG_INT(var, len,...)
Definition debug_lib.h:40
CK_SESSION_HANDLE session
#define SCP_KEY_LEN
Definition scp.h:37
#define SCP_MAC_LEN
Definition scp.h:46
#define SCP_PRF_LEN
Definition scp.h:38
#define SCP_HOST_CRYPTO_LEN
Definition scp.h:44
unsigned short uint16_t
Definition stdint.h:125
unsigned char uint8_t
Definition stdint.h:124
Definition scp.h:56
struct _Msg::@103 st
uint8_t raw[3+SCP_MSG_BUF_SIZE]
Definition scp.h:62
yh_rc
Definition yubihsm.h:170
@ YHR_SESSION_AUTHENTICATION_FAILED
Returned value when failing to authenticate the session.
Definition yubihsm.h:191
yh_rc yrc
memset(pInfo->slotDescription, ' ', 64)
memcpy((char *) pInfo->slotDescription, s, l)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_begin_create_session_ext()

yh_rc yh_begin_create_session_ext ( yh_connector * connector,
uint16_t authkey_id,
uint8_t ** context,
uint8_t * card_cryptogram,
size_t card_cryptogram_len,
yh_session ** session )

Begin creating an external session. The session's encryption key and MAC key are not stored in the device.

This function must be followed by yh_finish_create_session_ext() to set the session keys.

Parameters
connectorConnector to the device
authkey_idObject ID of the Authentication Key used to authenticate the session
contextpointer to where context data is saved
card_cryptogramCard cryptogram
card_cryptogram_lenLength of card cryptogram
sessioncreated session
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_MEMORY_ERROR if failed to allocate memory for the session. See yh_rc for other possible errors
See also
Session

Definition at line 751 of file yubihsm.c.

754 {
755
756 Msg msg;
757 Msg response_msg;
758 yh_rc yrc;
759 uint8_t *ptr;
760 yh_session *new_session;
761 uint8_t host_challenge[YH_HOST_CHAL_LEN];
762
763 if (connector == NULL || context == NULL || card_cryptogram == NULL ||
764 card_cryptogram_len != SCP_CARD_CRYPTO_LEN || session == NULL) {
767 }
768
769 if (!rand_generate(host_challenge, sizeof(host_challenge))) {
770 return YHR_GENERIC_ERROR;
771 } // TODO(adma): take this as an input so that it can be generated from the
772 // YubiKey
773
774 /**********/
775 // TODO(adma): replace with func
776 new_session = calloc(1, sizeof(yh_session));
777 if (new_session == NULL) {
779 return YHR_MEMORY_ERROR;
780 }
781
782 // Send CREATE SESSION command
783 msg.st.cmd = YHC_CREATE_SESSION;
785
786 uint16_t authkey_id_n = htons(authkey_id);
787 memcpy(msg.st.data, &authkey_id_n, SCP_AUTHKEY_ID_LEN);
788 memcpy(msg.st.data + SCP_AUTHKEY_ID_LEN, host_challenge, SCP_HOST_CHAL_LEN);
789 memcpy(new_session->context, host_challenge, SCP_HOST_CHAL_LEN);
790
791 DBG_INT(host_challenge, SCP_HOST_CHAL_LEN, "Host challenge: ");
792
793 yrc = send_msg(connector, &msg, &response_msg);
794 if (yrc != YHR_SUCCESS) {
795 goto bcse_failure;
796 }
797
798 // Parse response
799 if (response_msg.st.cmd != YHC_CREATE_SESSION_R) {
800 yh_rc translated = translate_device_error(response_msg.st.data[0]);
801 DBG_ERR("Device error %s (%d)", yh_strerror(translated),
802 response_msg.st.data[0]);
803 yrc = translated;
804 goto bcse_failure;
805 }
806
807 if (response_msg.st.len != 1 + SCP_CARD_CHAL_LEN + SCP_CARD_CRYPTO_LEN) {
809 goto bcse_failure;
810 }
811
812 ptr = response_msg.st.data;
813
814 // Save sid
815 new_session->s.sid = (*ptr++);
816
817 // Save card challenge
819 ptr += SCP_CARD_CHAL_LEN;
820
821 memcpy(card_cryptogram, ptr, SCP_CARD_CRYPTO_LEN);
822 ptr += SCP_CARD_CRYPTO_LEN;
823
824 DBG_INFO("Received Session ID: %d", new_session->s.sid);
825
827 "Card challenge: ");
828 DBG_INT(card_cryptogram, SCP_CARD_CRYPTO_LEN, "Card cryptogram: ");
829
830 // Save link back to connector
831 new_session->parent = connector;
832
833 *session = new_session;
834 *context = new_session->context;
835
836 return YHR_SUCCESS;
837
838bcse_failure:
839 free(new_session);
840 (new_session) = NULL;
841
842 DBG_ERR("%s", yh_strerror(yrc));
843
844 return yrc;
845}
#define DBG_INFO(...)
Definition debug_lib.h:63
bool rand_generate(uint8_t *buf, size_t cb_buf)
Definition rand.c:27
#define SCP_CARD_CHAL_LEN
Definition scp.h:40
#define SCP_AUTHKEY_ID_LEN
Definition scp.h:50
#define SCP_HOST_CHAL_LEN
Definition scp.h:41
#define SCP_CARD_CRYPTO_LEN
Definition scp.h:43
uint8_t sid
Definition scp.h:69
struct yh_connector * parent
Definition internal.h:26
Scp_ctx s
Definition internal.h:31
uint8_t context[SCP_CONTEXT_LEN]
Definition internal.h:32
#define YH_HOST_CHAL_LEN
Length of host challenge for authentication.
Definition yubihsm.h:91
@ YHR_GENERIC_ERROR
Return value when encountering an unknown error.
Definition yubihsm.h:228
@ YHR_MEMORY_ERROR
Returned value when unable to allocate memory.
Definition yubihsm.h:174
@ YHR_WRONG_LENGTH
Definition yubihsm.h:185
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_capabilities_to_strings()

yh_rc yh_capabilities_to_strings ( const yh_capabilities * num,
const char * result[],
size_t * n_result )

Convert an array of yh_capabilities into strings separated by ','

Parameters
numArray of yh_capabilities
resultArray of the capabilies as strings
n_resultNumber of elements in result
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_BUFFER_TOO_SMALL if n_result is too small
See also
Capability

Definition at line 4168 of file yubihsm.c.

4169 {
4170
4171 if (num == 0 || result == NULL || n_result == NULL) {
4174 }
4175
4176 size_t matching = 0;
4177
4178 for (size_t i = 0; i < sizeof(yh_capability) / sizeof(yh_capability[0]);
4179 i++) {
4180 if (((1ULL << (yh_capability[i].bit % 8)) &
4181 num->capabilities[YH_CAPABILITIES_LEN - 1 -
4182 (yh_capability[i].bit / 8)]) != 0) {
4183 if (++matching > *n_result) {
4184 memset(result, 0, *n_result);
4185
4186 return YHR_BUFFER_TOO_SMALL;
4187 }
4188
4189 result[matching - 1] = yh_capability[i].name;
4190 }
4191 }
4192
4193 *n_result = matching;
4194
4195 return YHR_SUCCESS;
4196}
int bit
Definition yubihsm.h:566
#define YH_CAPABILITIES_LEN
Length of capabilities array.
Definition yubihsm.h:119
@ YHR_BUFFER_TOO_SMALL
Returned value when there is not enough space to store data.
Definition yubihsm.h:187
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_check_capability()

bool yh_check_capability ( const yh_capabilities * capabilities,
const char * capability )

Check if a capability is set

Parameters
capabilitiesArray of yh_capabilities
capabilityCapability to check as a string.
Returns
True if the capability is in capabilities. False otherwise
Code sample
char *capabilities_str = "sign-pkcs,decrypt-pkcs,set-option";
yh_capabilities capabilities = {{0}};
yh_string_to_capabilities(capabilities_str, &capabilities);
//yh_check_capability(&capabilities, "something") => false
//yh_check_capability(&capabilities, "sign-pss") => false
//yh_check_capability(&capabilities, "decrypt-pkcs") => true
See also
Capability

Definition at line 4198 of file yubihsm.c.

4199 {
4200
4201 yh_capabilities check_capabilities = {{0}};
4202
4203 if (yh_string_to_capabilities(capability, &check_capabilities) !=
4204 YHR_SUCCESS) {
4205 return false;
4206 }
4207
4208 for (int i = 0; i < YH_CAPABILITIES_LEN; i++) {
4209 if (check_capabilities.capabilities[i] != 0 &&
4210 (check_capabilities.capabilities[i] & capabilities->capabilities[i]) !=
4211 0) {
4212 return true;
4213 }
4214 }
4215
4216 return false;
4217}
Capabilities representation.
Definition yubihsm.h:162
uint8_t capabilities[YH_CAPABILITIES_LEN]
Capabilities is represented as an 8 byte uint8_t array.
Definition yubihsm.h:164
yh_rc yh_string_to_capabilities(const char *capability, yh_capabilities *result)
Definition yubihsm.c:4115
yh_capabilities capabilities
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_connect()

yh_rc yh_connect ( yh_connector * connector,
int timeout )

Connect to the device through the specified connector

Parameters
connectorConnector to the device
timeoutConnection timeout in seconds
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the connector does not exist. See yh_rc for other possible errors

Definition at line 4079 of file yubihsm.c.

4079 {
4080
4081 if (connector == NULL || connector->bf == NULL) {
4082 DBG_ERR("Invalid parameters: undefined pointer");
4084 }
4085
4086 yh_rc rc;
4087
4088 rc = connector->bf->backend_connect(connector, timeout);
4089
4090 if (rc != YHR_SUCCESS) {
4091 DBG_ERR("Failed when connecting: %s", yh_strerror(rc));
4092 }
4093
4094 return rc;
4095}
struct backend_functions * bf
Definition internal.h:39
yh_rc rc
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_connector_has_device()

bool yh_connector_has_device ( yh_connector * connector)

Check if the connector has a device connected

Parameters
connectorConnector currently in use
Returns
True if the connector is not NULL and there is a device connected to it. False otherwise

Definition at line 906 of file yubihsm.c.

906 {
907
908 return connector && connector->has_device;
909}
bool has_device
Definition internal.h:43
Here is the caller graph for this function:

◆ yh_create_session()

yh_rc yh_create_session ( yh_connector * connector,
uint16_t authkey_id,
const uint8_t * key_enc,
size_t key_enc_len,
const uint8_t * key_mac,
size_t key_mac_len,
bool recreate_session,
yh_session ** session )

Create a session that uses the specified encryption key and MAC key to derive session-specific keys

Parameters
connectorConnector to the device
authkey_idObject ID of the Authentication Key used to authenticate the session
key_encEncryption key used to derive the session encryption key
key_enc_lenLength of the encryption key.
key_macMAC key used to derive the session MAC key
key_mac_lenLength of the MAC key.
recreate_sessionIf true, the session will be recreated if expired. This caches the password in memory
sessioncreated session
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or incorrect. See yh_rc for other possible errors
See also
Session, Authentication Key

Definition at line 616 of file yubihsm.c.

619 {
620
621 Msg msg;
622 Msg response_msg;
623 yh_rc yrc;
624 uint8_t *ptr;
625 uint8_t card_cryptogram[SCP_CARD_CRYPTO_LEN];
626 yh_session *new_session;
627 uint8_t host_challenge[YH_HOST_CHAL_LEN];
628
629 if (connector == NULL || key_enc == NULL || key_enc_len != SCP_KEY_LEN ||
630 key_mac == NULL || key_mac_len != SCP_KEY_LEN || session == NULL) {
633 }
634
635 if (!rand_generate(host_challenge, sizeof(host_challenge))) {
636 return YHR_GENERIC_ERROR;
637 }
638
639 if (!*session) {
640 new_session = calloc(1, sizeof(yh_session));
641 if (new_session == NULL) {
643 return YHR_MEMORY_ERROR;
644 }
645 } else {
646 new_session = *session;
647 }
648
649 new_session->authkey_id = authkey_id;
650
651 if (recreate) {
652 new_session->recreate = true;
653 memcpy(new_session->key_enc, key_enc, SCP_KEY_LEN);
654 memcpy(new_session->key_mac, key_mac, SCP_KEY_LEN);
655 }
656
657 // Send CREATE SESSION command
658 msg.st.cmd = YHC_CREATE_SESSION;
660
661 uint16_t authkey_id_n = htons(authkey_id);
662 memcpy(msg.st.data, &authkey_id_n, SCP_AUTHKEY_ID_LEN);
663 memcpy(msg.st.data + SCP_AUTHKEY_ID_LEN, host_challenge, SCP_HOST_CHAL_LEN);
664 memcpy(new_session->context, host_challenge, SCP_HOST_CHAL_LEN);
665
666 DBG_INT(host_challenge, SCP_HOST_CHAL_LEN, "Host challenge: ");
667
668 yrc = send_msg(connector, &msg, &response_msg);
669 if (yrc != YHR_SUCCESS) {
670 goto cs_failure;
671 }
672
673 // Parse response
674 if (response_msg.st.cmd != YHC_CREATE_SESSION_R) {
675 yh_rc translated = translate_device_error(response_msg.st.data[0]);
676 DBG_ERR("Device error %s (%d)", yh_strerror(translated),
677 response_msg.st.data[0]);
678 yrc = translated;
679 goto cs_failure;
680 }
681
682 if (response_msg.st.len != 1 + SCP_CARD_CHAL_LEN + SCP_CARD_CRYPTO_LEN) {
684 goto cs_failure;
685 }
686
687 ptr = response_msg.st.data;
688
689 // Save sid
690 new_session->s.sid = (*ptr++);
691
692 // Save card challenge
694 ptr += SCP_CARD_CHAL_LEN;
695
696 memcpy(card_cryptogram, ptr, SCP_CARD_CRYPTO_LEN);
697 ptr += SCP_CARD_CRYPTO_LEN;
698
699 DBG_INFO("Received Session ID: %d", new_session->s.sid);
700
702 "Card challenge: ");
703 DBG_INT(card_cryptogram, SCP_CARD_CRYPTO_LEN, "Card cryptogram: ");
704
705 // Derive session keys
706 yrc =
707 derive_s_enc(&new_session->s, key_enc, key_enc_len, new_session->context);
708 if (yrc != YHR_SUCCESS)
709 goto cs_failure;
710
711 yrc =
712 derive_s_mac(&new_session->s, key_mac, key_mac_len, new_session->context);
713 if (yrc != YHR_SUCCESS)
714 goto cs_failure;
715
716 yrc =
717 derive_s_rmac(&new_session->s, key_mac, key_enc_len, new_session->context);
718 if (yrc != YHR_SUCCESS)
719 goto cs_failure;
720
721 DBG_INT(new_session->s.s_enc, SCP_KEY_LEN, "S-ENC: ");
722 DBG_INT(new_session->s.s_mac, SCP_KEY_LEN, "S-MAC: ");
723 DBG_INT(new_session->s.s_rmac, SCP_KEY_LEN, "S-RMAC: ");
724 // Verify card cryptogram
725 yrc = verify_card_cryptogram(&new_session->s, new_session->context,
726 card_cryptogram);
727 if (yrc != YHR_SUCCESS) {
728 DBG_ERR("%s", yh_strerror(yrc));
729 goto cs_failure;
730 }
731
732 DBG_INFO("Card cryptogram successfully verified");
733
734 // Save link back to connector
735 new_session->parent = connector;
736
737 *session = new_session;
738
739 return YHR_SUCCESS;
740
741cs_failure:
742 insecure_memzero(new_session, sizeof(yh_session));
743 free(new_session);
744 (new_session) = NULL;
745
746 DBG_ERR("%s", yh_strerror(yrc));
747
748 return yrc;
749}
#define insecure_memzero(buf, len)
uint8_t s_mac[SCP_KEY_LEN]
Definition scp.h:71
uint8_t s_rmac[SCP_KEY_LEN]
Definition scp.h:72
uint8_t s_enc[SCP_KEY_LEN]
Definition scp.h:70
bool recreate
Definition internal.h:28
uint8_t key_enc[SCP_KEY_LEN]
Definition internal.h:29
uint16_t authkey_id
Definition internal.h:27
uint8_t key_mac[SCP_KEY_LEN]
Definition internal.h:30
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_create_session_derived()

yh_rc yh_create_session_derived ( yh_connector * connector,
uint16_t authkey_id,
const uint8_t * password,
size_t password_len,
bool recreate_session,
yh_session ** session )

Create a session that uses an encryption key and a MAC key derived from a password

Parameters
connectorConnector to the device
authkey_idObject ID of the Authentication Key used to authenticate the session
passwordPassword used to derive the session encryption key and MAC key
password_lenLength of the password in bytes
recreate_sessionIf true, the session will be recreated if expired. This caches the password in memory
sessionThe created session
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the connector, the password or the session are NULL. YHR_GENERIC_ERROR if failed to derive the session encryption key and/or the MAC key or if PRNG related errors occur. YHR_MEMORY_ERROR if failed to allocate memory for the session. See yh_rc for other possible errors
See also
Session

Definition at line 593 of file yubihsm.c.

595 {
596
597 if (connector == NULL || password == NULL || session == NULL) {
600 }
601
602 uint8_t key_enc[SCP_KEY_LEN];
603 uint8_t key_mac[SCP_KEY_LEN];
604
605 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
606
607 if (yrc == YHR_SUCCESS) {
608 yrc = yh_create_session(connector, authkey_id, key_enc, SCP_KEY_LEN,
609 key_mac, SCP_KEY_LEN, recreate, session);
610 insecure_memzero(key_enc, sizeof(key_enc));
611 insecure_memzero(key_mac, sizeof(key_mac));
612 }
613 return yrc;
614}
yh_rc yh_create_session(yh_connector *connector, uint16_t authkey_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate, yh_session **session)
Definition yubihsm.c:616
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_destroy_session()

yh_rc yh_destroy_session ( yh_session ** session)

Free data associated with the session

Parameters
sessionPointer to the session to destroy
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL.
See also
Session

Definition at line 890 of file yubihsm.c.

890 {
891
892 if (session == NULL) {
895 } else if (*session == NULL) {
896 return YHR_SUCCESS;
897 }
898
900 free(*session);
901 *session = NULL;
902
903 return YHR_SUCCESS;
904}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_disconnect()

yh_rc yh_disconnect ( yh_connector * connector)

Disconnect from a connector

Parameters
connectorConnector from which to disconnect
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the connector is NULL

Definition at line 4097 of file yubihsm.c.

4097 {
4098
4099 if (connector == NULL) {
4102 }
4103
4104 destroy_connector(connector);
4105
4106 return YHR_SUCCESS;
4107}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_domains_to_string()

yh_rc yh_domains_to_string ( uint16_t domains,
char * string,
size_t max_len )

Convert domains parameter to its String representation

Parameters
domainsEncoded domains
stringDomains as a string
max_lenMaximum length of the string
Returns
YHR_SUCCESS if successful. YHR_BUFFER_TOO_SMALL if max_len is too small
Examples
  • 1 => "1"
  • 0x8001 => "1:16"
  • 0, ""
  • 0xffff => "1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16"
See also
Domains

Definition at line 4587 of file yubihsm.c.

4587 {
4588 char *ptr = string;
4589 *ptr = '\0';
4590 for (uint16_t i = 0; i < YH_MAX_DOMAINS; i++) {
4591 if (domains & (1 << i)) {
4592 size_t wrote = snprintf(ptr, max_len, "%d:", i + 1);
4593 if (wrote >= max_len) {
4594 return YHR_BUFFER_TOO_SMALL;
4595 }
4596 ptr += wrote;
4597 max_len -= wrote;
4598 }
4599 }
4600 if (ptr != string) {
4601 *(ptr - 1) = '\0';
4602 }
4603 return YHR_SUCCESS;
4604}
#define YH_MAX_DOMAINS
Max number of domains.
Definition yubihsm.h:125
uint16_t domains
Here is the caller graph for this function:

◆ yh_exit()

yh_rc yh_exit ( void )

Global library clean up

Returns
YHR_SUCCESS

Definition at line 3910 of file yubihsm.c.

3910{ return YHR_SUCCESS; }
Here is the caller graph for this function:

◆ yh_filter_capabilities()

yh_rc yh_filter_capabilities ( const yh_capabilities * capabilities,
const yh_capabilities * filter,
yh_capabilities * result )

Filter one set of capabilities with another. The resulting set of capabilities contains only the capabilities that exist in both sets of input capabilities

Parameters
capabilitiesArray of yh_capabilities
filterArray of yh_capabilities
resultResulting array of yh_capabilities
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL.
See also
Capability

Definition at line 4231 of file yubihsm.c.

4233 {
4234 if (capabilities == NULL || filter == NULL || result == NULL) {
4236 }
4237
4238 for (int i = 0; i < YH_CAPABILITIES_LEN; i++) {
4239 result->capabilities[i] =
4240 capabilities->capabilities[i] & filter->capabilities[i];
4241 }
4242 return YHR_SUCCESS;
4243}

◆ yh_finish_create_session_ext()

yh_rc yh_finish_create_session_ext ( yh_connector * connector,
yh_session * session,
const uint8_t * key_senc,
size_t key_senc_len,
const uint8_t * key_smac,
size_t key_smac_len,
const uint8_t * key_srmac,
size_t key_srmac_len,
uint8_t * card_cryptogram,
size_t card_cryptogram_len )

Finish creating external session. The session's encryption key and MAC key are not stored in the device.

This function must be called after yh_begin_create_session_ext().

Parameters
connectorConnector to the device
sessionThe session created with yh_begin_create_session_ext()
key_sencSession encryption key used to encrypt the messages exchanged with the device
key_senc_lenLenght of the encryption key. Must be YH_KEY_LEN
key_smacSession MAC key used for creating the authentication tag for each message
key_smac_lenLength of the MAC key. Must be YH_KEY_LEN
key_srmacSession return MAC key used for creating the authentication tag for each response message
key_srmac_lenLength of the return MAC key. Must be YH_KEY_LEN
card_cryptogramCard cryptogram
card_cryptogram_lenLength of card cryptogram
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or any of the key lengths are not YH_KEY_LEN. See yh_rc for other possible errors
See also
Session

Definition at line 847 of file yubihsm.c.

851 { // TODO(adma): remove all these
852
853 if (connector == NULL || session == NULL || key_senc == NULL ||
854 key_senc_len != YH_KEY_LEN || key_smac == NULL ||
855 key_smac_len != YH_KEY_LEN || key_srmac == NULL ||
856 key_srmac_len != YH_KEY_LEN || card_cryptogram == NULL ||
857 card_cryptogram_len != SCP_CARD_CRYPTO_LEN) {
860 }
861
862 yh_rc yrc;
863
864 memcpy(session->s.s_enc, key_senc, key_senc_len);
865 memcpy(session->s.s_mac, key_smac, key_smac_len);
866 memcpy(session->s.s_rmac, key_srmac, key_srmac_len);
867
868 DBG_INT(session->s.s_enc, SCP_KEY_LEN, "S-ENC: ");
869 DBG_INT(session->s.s_mac, SCP_KEY_LEN, "S-MAC: ");
870 DBG_INT(session->s.s_rmac, SCP_KEY_LEN, "S-RMAC: ");
871
872 // Verify card cryptogram
873 yrc = verify_card_cryptogram(&session->s, session->context, card_cryptogram);
874 if (yrc != YHR_SUCCESS) {
875 DBG_ERR("%s", yh_strerror(yrc));
876
877 free(session);
878 session = NULL;
879
880 DBG_ERR("%s", yh_strerror(yrc));
881
882 return yrc;
883 }
884
885 DBG_INFO("Card cryptogram successfully verified");
886
887 return YHR_SUCCESS;
888}
#define YH_KEY_LEN
Length of authentication keys.
Definition yubihsm.h:95
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_get_connector_address()

yh_rc yh_get_connector_address ( yh_connector * connector,
char **const address )

Get connector address

Parameters
connectorConnector currently in use
addressPointer to the connector address as string
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL.

Definition at line 926 of file yubihsm.c.

926 {
927
928 if (connector == NULL || address == NULL) {
931 }
932
933 *address = (char *) connector->address;
934
935 return YHR_SUCCESS;
936}
uint8_t address[32]
Definition internal.h:47
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_get_connector_version()

yh_rc yh_get_connector_version ( yh_connector * connector,
uint8_t * major,
uint8_t * minor,
uint8_t * patch )

Get the connector version

Parameters
connectorConnector currently in use
majorConnector major version
minorConnector minor version
patchConnector patch version
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL.

Definition at line 911 of file yubihsm.c.

912 {
913
914 if (connector == NULL || major == NULL || minor == NULL || patch == NULL) {
917 }
918
919 *major = connector->version_major;
920 *minor = connector->version_minor;
921 *patch = connector->version_patch;
922
923 return YHR_SUCCESS;
924}
uint8_t version_patch
Definition internal.h:46
uint8_t version_minor
Definition internal.h:45
uint8_t version_major
Definition internal.h:44
uint8_t patch
uint8_t major
uint8_t minor
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_get_key_bitlength()

yh_rc yh_get_key_bitlength ( yh_algorithm algorithm,
size_t * result )

Get the expected key length of a key generated by the given algorithm

Parameters
algorithmAlgorithm to check. See yh_algorithm
resultExpected bitlength of a key generated by the algorithm
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if result is NULL or if the algorithm is no supported by YubiHSM 2. For a list of supported algorithms, see yh_algorithm

Definition at line 4309 of file yubihsm.c.

4309 {
4310
4311 if (result == NULL) {
4313 }
4314
4315 switch (algorithm) {
4316 case YH_ALGO_RSA_2048:
4317 *result = 2048;
4318 break;
4319
4320 case YH_ALGO_RSA_3072:
4321 *result = 3072;
4322 break;
4323
4324 case YH_ALGO_RSA_4096:
4325 *result = 4096;
4326 break;
4327
4328 case YH_ALGO_EC_P256:
4329 *result = 256;
4330 break;
4331
4332 case YH_ALGO_EC_P384:
4333 *result = 384;
4334 break;
4335
4336 case YH_ALGO_EC_P521:
4337 *result = 521;
4338 break;
4339
4340 case YH_ALGO_EC_P224:
4341 *result = 224;
4342 break;
4343
4344 case YH_ALGO_EC_K256:
4345 *result = 256;
4346 break;
4347
4348 case YH_ALGO_EC_BP256:
4349 *result = 256;
4350 break;
4351
4352 case YH_ALGO_EC_BP384:
4353 *result = 394;
4354 break;
4355
4356 case YH_ALGO_EC_BP512:
4357 *result = 512;
4358 break;
4359
4360 case YH_ALGO_HMAC_SHA1:
4361 *result = 160;
4362 break;
4363
4365 *result = 256;
4366 break;
4367
4369 *result = 384;
4370 break;
4371
4373 *result = 512;
4374 break;
4375
4376 default:
4377 *result = 0;
4379 }
4380
4381 return YHR_SUCCESS;
4382}
@ YH_ALGO_EC_P521
ecp521
Definition yubihsm.h:418
@ YH_ALGO_EC_BP384
ecbp384
Definition yubihsm.h:424
@ YH_ALGO_EC_P384
ecp384
Definition yubihsm.h:416
@ YH_ALGO_HMAC_SHA512
hmac-sha512
Definition yubihsm.h:434
@ YH_ALGO_HMAC_SHA384
hmac-sha384
Definition yubihsm.h:432
@ YH_ALGO_HMAC_SHA1
hmac-sha1
Definition yubihsm.h:428
@ YH_ALGO_RSA_2048
rsa2048
Definition yubihsm.h:408
@ YH_ALGO_HMAC_SHA256
hmac-sha256
Definition yubihsm.h:430
@ YH_ALGO_EC_BP512
ecbp512
Definition yubihsm.h:426
@ YH_ALGO_EC_BP256
ecbp256
Definition yubihsm.h:422
@ YH_ALGO_EC_K256
eck256
Definition yubihsm.h:420
@ YH_ALGO_EC_P256
ecp256
Definition yubihsm.h:414
@ YH_ALGO_RSA_4096
rsa4096
Definition yubihsm.h:412
@ YH_ALGO_EC_P224
ecp224
Definition yubihsm.h:484
@ YH_ALGO_RSA_3072
rsa3072
Definition yubihsm.h:410
Here is the caller graph for this function:

◆ yh_get_session_id()

yh_rc yh_get_session_id ( yh_session * session,
uint8_t * sid )

Get the session ID

Parameters
sessionAuthenticated session to use
sidSession ID
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL.

Definition at line 2915 of file yubihsm.c.

2915 {
2916
2917 if (session == NULL || sid == NULL) {
2920 }
2921
2922 *sid = session->s.sid;
2923
2924 return YHR_SUCCESS;
2925}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_get_verbosity()

yh_rc yh_get_verbosity ( uint8_t * verbosity)

Get verbosity level when executing commands

Parameters
verbosityThe verbosity level
Returns
YHR_SUCCESS if seccessful. YHR_INVALID_PARAMETERS if verbosity is NULL
See also
YH_VERB_QUIET, YH_VERB_INTERMEDIATE, YH_VERB_CRYPTO, YH_VERB_RAW, YH_VERB_INFO, YH_VERB_ERR, YH_VERB_ALL

Definition at line 3837 of file yubihsm.c.

3837 {
3838
3839 if (verbosity == NULL) {
3841 }
3842
3843 *verbosity = _yh_verbosity;
3844
3845 return YHR_SUCCESS;
3846}
uint8_t _yh_verbosity
Here is the caller graph for this function:

◆ yh_init()

yh_rc yh_init ( void )

Global library initialization

Returns
YHR_SUCCESS

Definition at line 3857 of file yubihsm.c.

3857 {
3858 if (_yh_output == NULL) {
3859 _yh_output = stderr;
3860 }
3861 return YHR_SUCCESS;
3862}
FILE * _yh_output
Here is the caller graph for this function:

◆ yh_init_connector()

yh_rc yh_init_connector ( const char * url,
yh_connector ** connector )

Instantiate a new connector

Parameters
urlURL associated with this connector
connectorConnector to the device
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if either the URL or the connector are NULL. YHR_GENERIC_ERROR if failed to load the backend. YHR_MEMORY_ERROR if failed to allocate memory for the connector. YHR_CONNECTION_ERROR if failed to create the connector

Definition at line 4024 of file yubihsm.c.

4024 {
4025 if (url == NULL || connector == NULL) {
4026 DBG_ERR("Invalid parameters: undefined pointer");
4028 }
4029
4030#ifdef STATIC
4031#define USB_LIB STATIC_USB_BACKEND
4032#define HTTP_LIB STATIC_HTTP_BACKEND
4033#elif defined WIN32
4034#define USB_LIB "libyubihsm_usb.dll"
4035#define HTTP_LIB "libyubihsm_http.dll"
4036#elif defined __APPLE__
4037#define USB_LIB "libyubihsm_usb." SOVERSION ".dylib"
4038#define HTTP_LIB "libyubihsm_http." SOVERSION ".dylib"
4039#else
4040#define USB_LIB "libyubihsm_usb.so." SOVERSION
4041#define HTTP_LIB "libyubihsm_http.so." SOVERSION
4042#endif
4043
4044 void *backend = NULL;
4045 struct backend_functions *bf = NULL;
4046
4047 if (strncmp(url, YH_USB_URL_SCHEME, strlen(YH_USB_URL_SCHEME)) == 0) {
4048 DBG_INFO("Loading usb backend");
4049 load_backend(USB_LIB, &backend, &bf);
4050 } else if (strncmp(url, "http://", strlen("http://")) == 0 ||
4051 strncmp(url, "https://", strlen("https://")) == 0) {
4052 DBG_INFO("Loading http backend");
4053 load_backend(HTTP_LIB, &backend, &bf);
4054 }
4055 if (bf == NULL) {
4056 DBG_ERR("Failed loading the backend");
4057 return YHR_GENERIC_ERROR;
4058 }
4059
4060 return create_connector(connector, url, backend, bf);
4061}
string url
Definition main.cpp:166
#define USB_LIB
#define HTTP_LIB
#define YH_USB_URL_SCHEME
URL scheme used for direct USB access.
Definition yubihsm.h:129
Here is the caller graph for this function:

◆ yh_is_ec()

bool yh_is_ec ( yh_algorithm algorithm)

Check if an algorithm is a supported Elliptic Curve algorithm.

Supported EC algorithms: YH_ALGO_EC_P224, YH_ALGO_EC_P256, YH_ALGO_EC_P384, YH_ALGO_EC_P521, YH_ALGO_EC_K256, YH_ALGO_EC_BP256, YH_ALGO_EC_BP384 and YH_ALGO_EC_BP512

Parameters
algorithmAlgorithm to check. See yh_algorithm
Returns
True if the algorithm is one of the supported EC algorithms. False otherwise

Definition at line 4260 of file yubihsm.c.

4260 {
4261
4262 switch (algorithm) {
4263 case YH_ALGO_EC_P224:
4264 case YH_ALGO_EC_P256:
4265 case YH_ALGO_EC_P384:
4266 case YH_ALGO_EC_P521:
4267 case YH_ALGO_EC_K256:
4268 case YH_ALGO_EC_BP256:
4269 case YH_ALGO_EC_BP384:
4270 case YH_ALGO_EC_BP512:
4271 return true;
4272
4273 default:
4274 break;
4275 }
4276
4277 return false;
4278}
Here is the caller graph for this function:

◆ yh_is_ed()

bool yh_is_ed ( yh_algorithm algorithm)

Check if an algorithm is a supported ED algorithm.

Supported ED algorithms: YH_ALGO_EC_ED25519

Parameters
algorithmalgorithm. See yh_algorithm
Returns
True if the algorithm is YH_ALGO_EC_ED25519. False otherwise

Definition at line 4280 of file yubihsm.c.

4280 {
4281
4282 switch (algorithm) {
4283 case YH_ALGO_EC_ED25519:
4284 return true;
4285
4286 default:
4287 break;
4288 }
4289
4290 return false;
4291}
@ YH_ALGO_EC_ED25519
ed25519
Definition yubihsm.h:482
Here is the caller graph for this function:

◆ yh_is_hmac()

bool yh_is_hmac ( yh_algorithm algorithm)

Check if algorithm is a supported HMAC algorithm.

Supported HMAC algorithms: YH_ALGO_HMAC_SHA1, YH_ALGO_HMAC_SHA256, YH_ALGO_HMAC_SHA384 and YH_ALGO_HMAC_SHA512

Parameters
algorithmAlgorithm to check. See yh_algorithm
Returns
True if the algorithm is one of the supported HMAC algorithms. False otherwise

Definition at line 4293 of file yubihsm.c.

4293 {
4294
4295 switch (algorithm) {
4296 case YH_ALGO_HMAC_SHA1:
4300 return true;
4301
4302 default:
4303 break;
4304 }
4305
4306 return false;
4307}
Here is the caller graph for this function:

◆ yh_is_rsa()

bool yh_is_rsa ( yh_algorithm algorithm)

Check if an algorithm is a supported RSA algorithm.

Supported RSA algorithms: YH_ALGO_RSA_2048, YH_ALGO_RSA_3072 and YH_ALGO_RSA_4096

Parameters
algorithmAlgorithm to check. See yh_algorithm
Returns
True if the algorithm is one of the supported RSA algorithms . False otherwise

Definition at line 4245 of file yubihsm.c.

4245 {
4246
4247 switch (algorithm) {
4248 case YH_ALGO_RSA_2048:
4249 case YH_ALGO_RSA_3072:
4250 case YH_ALGO_RSA_4096:
4251 return true;
4252
4253 default:
4254 break;
4255 }
4256
4257 return false;
4258}
Here is the caller graph for this function:

◆ yh_merge_capabilities()

yh_rc yh_merge_capabilities ( const yh_capabilities * a,
const yh_capabilities * b,
yh_capabilities * result )

Merge two sets of capabilities. The resulting set of capabilities contain all capabilities from both arrays

Parameters
aArray of yh_capabilities
bArray of yh_capabilities
resultResulting array of yh_capabilities
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL.
See also
Capability

Definition at line 4219 of file yubihsm.c.

4220 {
4221 if (a == NULL || b == NULL || result == NULL) {
4223 }
4224
4225 for (int i = 0; i < YH_CAPABILITIES_LEN; i++) {
4226 result->capabilities[i] = a->capabilities[i] | b->capabilities[i];
4227 }
4228 return YHR_SUCCESS;
4229}
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181

◆ yh_send_plain_msg()

yh_rc yh_send_plain_msg ( yh_connector * connector,
yh_cmd cmd,
const uint8_t * data,
size_t data_len,
yh_cmd * response_cmd,
uint8_t * response,
size_t * response_len )

Send a plain (unencrypted) message to the device through a connector

Parameters
connectorConnector to the device
cmdCommand to send. See yh_cmd
dataData to send
data_lenlength of data to send
response_cmdResponse command
responseResponse data
response_lenLength of response data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_BUFFER_TOO_SMALL if the actual response was longer than response_len. See yh_rc for other possible errors

Definition at line 126 of file yubihsm.c.

129 {
130
131 Msg msg;
132 Msg response_msg;
133
134 yh_rc yrc;
135
136 if (connector == NULL || (data_len != 0 && data == NULL) ||
137 response_cmd == NULL || response == NULL || response_len == NULL) {
140 }
141
142 if (data_len > sizeof(msg.st.data)) {
143 DBG_ERR("Tried to transfer oversized data (%zu > %zu)", data_len,
144 sizeof(msg.st.data));
146 }
147
148 msg.st.cmd = cmd;
149 msg.st.len = data_len;
150 if (data_len > 0) {
151 memcpy(msg.st.data, data, data_len);
152 }
153
154 DBG_DUMPINFO(msg.raw, data_len + 3, "Sending cmd %02x (%3zu Bytes): ", cmd,
155 data_len + 3);
156
157 yrc = send_msg(connector, &msg, &response_msg);
158 if (yrc != YHR_SUCCESS) {
159 DBG_ERR("%s", yh_strerror(yrc));
160 return yrc;
161 }
162
163 if (*response_len < response_msg.st.len) {
164 DBG_DUMPERR(response_msg.raw, response_msg.st.len + 3,
165 "%s (received %3d Bytes, can fit %3zu Bytes) ",
166 yh_strerror(YHR_BUFFER_TOO_SMALL), response_msg.st.len,
167 *response_len);
169 }
170
171 *response_cmd = response_msg.st.cmd;
172
173 memcpy(response, response_msg.st.data, response_msg.st.len);
174 *response_len = response_msg.st.len;
175
176 return YHR_SUCCESS;
177}
#define DBG_DUMPERR(var, len,...)
Definition debug_lib.h:83
#define DBG_DUMPINFO(var, len,...)
Definition debug_lib.h:69
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_send_secure_msg()

yh_rc yh_send_secure_msg ( yh_session * session,
yh_cmd cmd,
const uint8_t * data,
size_t data_len,
yh_cmd * response_cmd,
uint8_t * response,
size_t * response_len )

Send an encrypted message to the device over a session. The session has to be authenticated

Parameters
sessionSession to send the message over
cmdCommand to send
dataData to send
data_lenLength of data to send
response_cmdResponse command
responseResponse data
response_lenLength of response data
Returns
YHR_SUCCESS if successful. See yh_rc for possible errors

Definition at line 416 of file yubihsm.c.

418 {
419
420 size_t saved_len = *response_len;
421
422 yh_rc yrc = _send_secure_msg(session, cmd, data, data_len, response_cmd,
423 response, response_len);
426 session->recreate) {
427 DBG_INFO("Recreating session");
428 yrc = yh_create_session(session->parent, session->authkey_id,
429 session->key_enc, SCP_KEY_LEN, session->key_mac,
430 SCP_KEY_LEN, true, &session);
431 if (yrc != YHR_SUCCESS) {
432 return yrc;
433 }
435 if (yrc != YHR_SUCCESS) {
436 return yrc;
437 }
438 *response_len = saved_len;
439 yrc = _send_secure_msg(session, cmd, data, data_len, response_cmd, response,
440 response_len);
441 }
442 return yrc;
443}
yh_rc yh_authenticate_session(yh_session *session)
Definition yubihsm.c:2927
@ YHR_DEVICE_INVALID_SESSION
Returned value when the device session is invalid.
Definition yubihsm.h:201
@ YHR_DEVICE_AUTHENTICATION_FAILED
Return value when the device fails to encrypt or verify the message.
Definition yubihsm.h:203
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_set_connector_option()

yh_rc yh_set_connector_option ( yh_connector * connector,
yh_connector_option opt,
const void * val )

Set connector options.

Note that backend options are not supported with winhttp or USB connectors

Parameters
connectorConnector to set an option on
optOption to set. See yh_connector_option
valValue of the option. Type of value is specific to the given option
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the connector or the value are NULL or if the option is unknown. YHR_CONNECTOR_ERROR if failed to set the option

Definition at line 4063 of file yubihsm.c.

4064 {
4065
4066 if (connector == NULL || val == NULL) {
4067 DBG_ERR("Invalid parameters: undefined pointer");
4069 }
4070
4071 if (connector->bf == NULL) {
4072 DBG_ERR("No backend loaded");
4074 }
4075
4076 return connector->bf->backend_option(connector->connection, opt, val);
4077}
yh_backend * connection
Definition internal.h:40
Here is the caller graph for this function:

◆ yh_set_debug_output()

void yh_set_debug_output ( yh_connector * connector,
FILE * output )

Set file for debug output

Parameters
connectorIf not NULL, the debug messages will be written to the specified output file
outputThe destination of the debug messages
Returns
void

Definition at line 3848 of file yubihsm.c.

3848 {
3849 _yh_output = output;
3850
3851 if (connector != NULL && connector->bf != NULL) {
3852 // TODO(adma): should we error out if NULL?
3853 connector->bf->backend_set_verbosity(_yh_verbosity, _yh_output);
3854 }
3855}
Here is the caller graph for this function:

◆ yh_set_verbosity()

yh_rc yh_set_verbosity ( yh_connector * connector,
uint8_t verbosity )

Set verbosity level when executing commands. Default verbosity is YH_VERB_QUIET

This function may be called prior to global library initialization to set the debug level

Parameters
connectorIf not NULL, the verbosity of the specific connector will be set
verbosityThe desired level of debug output
Returns
YHR_SUCCESS
See also
YH_VERB_QUIET, YH_VERB_INTERMEDIATE, YH_VERB_CRYPTO, YH_VERB_RAW, YH_VERB_INFO, YH_VERB_ERR, YH_VERB_ALL

Definition at line 3825 of file yubihsm.c.

3825 {
3826
3827 _yh_verbosity = verbosity;
3828
3829 if (connector != NULL && connector->bf != NULL) {
3830 // TODO(adma): should we error out if NULL?
3831 connector->bf->backend_set_verbosity(_yh_verbosity, _yh_output);
3832 }
3833
3834 return YHR_SUCCESS;
3835}
Here is the caller graph for this function:

◆ yh_string_to_algo()

yh_rc yh_string_to_algo ( const char * string,
yh_algorithm * algo )

Convert a string to an algorithm's numeric value

Parameters
stringAlgorithm as string. See yh_algorithm
algoAlgorithm numeric value
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if the algorithm is not supported by YubiHSM 2.
Code sample
yh_algorithm algorithm;
//yh_string_to_algo(NULL, &algorithm) => YHR_INVALID_PARAMETERS
//yh_string_to_algo("something", NULL) => YHR_INVALID_PARAMETERS
//yh_string_to_algo("something", &algorithm) => YHR_INVALID_PARAMETERS
//yh_string_to_algo("rsa-pkcs1-sha1", &algorithm) =>
YH_ALGO_RSA_PKCS1_SHA1 //yh_string_to_algo("rsa2048", &algorithm) => YH_ALGO_RSA_2048
See also
Algorithms

Definition at line 4403 of file yubihsm.c.

4403 {
4404
4405 if (string == NULL || algo == NULL) {
4408 }
4409 if (strcasecmp(string, "any") == 0) {
4410 *algo = 0;
4411 return YHR_SUCCESS;
4412 }
4413 for (size_t i = 0; i < sizeof(yh_algorithms) / sizeof(yh_algorithms[0]);
4414 i++) {
4415 if (strcasecmp(string, yh_algorithms[i].name) == 0) {
4416 *algo = yh_algorithms[i].algorithm;
4417 return YHR_SUCCESS;
4418 }
4419 }
4420
4422}
std::string name
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_string_to_capabilities()

yh_rc yh_string_to_capabilities ( const char * capability,
yh_capabilities * result )

Convert capability string to byte array

Parameters
capabilityString of capabilities separated by ',', ':' or '|'
resultArray of yh_capabilities
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_BUFFER_TOO_SMALL if capability is too big
Examples:
  • "get-opaque" => {"\x00\x00\x00\x00\x00\x00\x00\x01"}
  • "sign-hmac:verify-hmac|exportable-under-wrap," => {"\x00\x00\x00\x00\x00\xc1\x00\x00"}
  • ",,unwrap-data|:wrap-data,,," => {"\x00\x00\x00\x60\x00\x00\x00\x00"}
  • "0x7fffffffffffffff" => {"\x7f\xff\xff\xff\xff\xff\xff\xff"}
  • "0xffffffffffffffff" => {"\xff\xff\xff\xff\xff\xff\xff\xff"}
See also
Capability

Definition at line 4115 of file yubihsm.c.

4116 {
4117
4118 char *endptr;
4119 char *saveptr = NULL;
4120 char *str = NULL;
4121 char tmp[2048] = {0};
4123
4124 if (capability == NULL || result == NULL) {
4127 }
4128
4129 errno = 0;
4130 value = strtoull(capability, &endptr, 0);
4131
4132 if (capability != endptr && errno != ERANGE) {
4133 uint64_t actual = htonll(value);
4134 memcpy(result, &actual, 8);
4135 return YHR_SUCCESS;
4136 }
4137
4138 if (strcasecmp(capability, "all") == 0) {
4139 memset(result->capabilities, 0xff, YH_CAPABILITIES_LEN);
4140 return YHR_SUCCESS;
4141 } else if (strcasecmp(capability, "none") == 0) {
4142 memset(result->capabilities, 0x00, YH_CAPABILITIES_LEN);
4143 return YHR_SUCCESS;
4144 }
4145
4146 if (strlen(capability) > sizeof(tmp)) {
4147 return YHR_BUFFER_TOO_SMALL;
4148 }
4149 strncpy(tmp, capability, sizeof(tmp) - 1);
4150
4151 while ((str = strtok_r(str ? NULL : tmp, LIST_SEPARATORS, &saveptr))) {
4152 for (size_t i = 0; i < sizeof(yh_capability) / sizeof(yh_capability[0]);
4153 i++) {
4154 if (strcasecmp(str, yh_capability[i].name) == 0) {
4155 result
4156 ->capabilities[YH_CAPABILITIES_LEN - 1 - yh_capability[i].bit / 8] |=
4157 1ULL << (yh_capability[i].bit % 8);
4158 break;
4159 } else if (i + 1 == sizeof(yh_capability) / sizeof(yh_capability[0])) {
4161 }
4162 }
4163 }
4164
4165 return YHR_SUCCESS;
4166}
return str
Definition CLI11.hpp:1359
#define value
Definition pkcs11.h:157
#define htonll(x)
Definition yubihsm.c:4110
#define LIST_SEPARATORS
Definition yubihsm.c:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_string_to_domains()

yh_rc yh_string_to_domains ( const char * domains,
uint16_t * result )

Convert a string to a domain's numeric value.

The domains string can contain one or several domains separated by ',', ':' or '|'. Each domain can be written in decimal or hex format

Parameters
domainsString of domains
resultResulting parsed domains as an unsigned int
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL, if the domains string is does not contains the expected values
Examples
  • "1" => 1
  • "1,2:3,4|5,6;7,8,9,10,11,12,13,14,15,16" => 0xffff
  • "1,16" => 0x8001
  • "16" => 0x8000
  • "16,15" => 0xc000
  • "1,0xf" => 0x4001
  • "0x1,0x2" => 3
  • "0x8888" => 0x8888
  • "0" => 0
  • "all" => 0xffff
  • "2" => 2
  • "2:4" => 10
See also
Domains

Definition at line 4535 of file yubihsm.c.

4535 {
4536 char *endptr;
4537 char *saveptr = NULL;
4538 char *str = NULL;
4539 char tmp[64] = {0};
4540 unsigned long value;
4541
4542 if (domains == NULL || result == NULL) {
4545 }
4546 *result = 0;
4547
4548 if (strcasecmp(domains, "all") == 0) {
4549 *result = 0xffff;
4550 goto out;
4551 } else if (strcmp(domains, "0") == 0) {
4552 goto out;
4553 }
4554
4555 errno = 0;
4556 value = strtoul(domains, &endptr, 0);
4557
4558 if (strncmp(domains, "0x", 2) == 0 && *endptr == '\0' && errno != ERANGE &&
4559 value != ULONG_MAX) {
4560 if (value > USHRT_MAX) {
4561 DBG_ERR("Tried to parse to long number for domains");
4563 }
4564 *result = value;
4565 } else {
4566 if (strlen(domains) > sizeof(tmp)) {
4567 return YHR_BUFFER_TOO_SMALL;
4568 }
4569 strncpy(tmp, domains, sizeof(tmp) - 1);
4570
4571 while ((str = strtok_r(str ? NULL : tmp, LIST_SEPARATORS, &saveptr))) {
4572 endptr = NULL;
4573 value = strtoul(str, &endptr, 0);
4574 if (errno == ERANGE || value > YH_MAX_DOMAINS || value == 0) {
4575 DBG_ERR("Domains are numbered from 1 to %d", YH_MAX_DOMAINS);
4577 }
4578 *result |= 1 << (value - 1);
4579 }
4580 }
4581
4582out:
4583 DBG_INFO("Domains parsed as %x", *result);
4584 return YHR_SUCCESS;
4585}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_string_to_option()

yh_rc yh_string_to_option ( const char * string,
yh_option * option )

Convert a string to an option's numeric value

Parameters
stringOption as string. See yh_option
optionOption numeric value
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if the option was not recognized.
Code sample
yh_option option;
//yh_string_to_option(NULL, &option) => YHR_INVALID_PARAMETERS
//yh_string_to_option("something", NULL) => YHR_INVALID_PARAMETERS
//yh_string_to_option("something", &option) => YHR_INVALID_PARAMETERS
//yh_string_to_option("force-audit", &option) =>
option=YH_OPTION_FORCE_AUDIT
See also
Options

Definition at line 4463 of file yubihsm.c.

4463 {
4464
4465 if (string == NULL || option == NULL) {
4468 }
4469
4470 for (size_t i = 0; i < sizeof(yh_options) / sizeof(yh_options[0]); i++) {
4471 if (strcasecmp(string, yh_options[i].name) == 0) {
4472 *option = yh_options[i].option;
4473 return YHR_SUCCESS;
4474 }
4475 }
4476
4478}
yh_option option
Definition yubihsm.h:685
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_string_to_type()

yh_rc yh_string_to_type ( const char * string,
yh_object_type * type )

Convert a string to a type's numeric value

Parameters
stringType as a String. See yh_object_type
typeType numeric value
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if the type was not recognized.
Code sample
yh_object_type type;
//yh_string_to_type(NULL, &type) => YHR_INVALID_PARAMETERS
//yh_string_to_type("something", NULL) => YHR_INVALID_PARAMETERS
//yh_string_to_type("something", &type) => YHR_INVALID_PARAMETERS
//yh_string_to_type("opaque", &type) => type=YH_OPAQUE
//yh_string_to_type("authentication-key", &type) =>
type=YH_AUTHENTICATION_KEY
See also
Object

Definition at line 4442 of file yubihsm.c.

4442 {
4443
4444 if (string == NULL || type == NULL) {
4447 }
4448
4449 if (strcasecmp(string, "any") == 0) {
4450 *type = 0;
4451 return YHR_SUCCESS;
4452 }
4453 for (size_t i = 0; i < sizeof(yh_types) / sizeof(yh_types[0]); i++) {
4454 if (strcasecmp(string, yh_types[i].name) == 0) {
4455 *type = yh_types[i].type;
4456 return YHR_SUCCESS;
4457 }
4458 }
4459
4461}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_type_to_string()

yh_rc yh_type_to_string ( yh_object_type type,
char const ** result )

Convert a yh_object_type to its string representation

Parameters
typeType to convert. See yh_object_type
resultThe type as a String. "Unknown" if the type was not recognized
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if result is NULL.
Code sample
const char *string;
//yh_type_to_string(0, NULL) => YHR_INVALID_PARAMETERS
//yh_type_to_string(99, &string) => string="Unknown"
//yh_type_to_string(YH_OPAQUE, &string) => string="opaque"
//yh_type_to_string(YH_AUTHENTICATION_KEY, &string) =>
string="authentication-key"
See also
Object

Definition at line 4424 of file yubihsm.c.

4424 {
4425
4426 if (result == NULL) {
4429 }
4430
4431 for (size_t i = 0; i < sizeof(yh_types) / sizeof(yh_types[0]); i++) {
4432 if (type == yh_types[i].type) {
4433 *result = yh_types[i].name;
4434 return YHR_SUCCESS;
4435 }
4436 }
4437
4438 *result = "Unknown";
4439 return YHR_SUCCESS;
4440}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_blink_device()

yh_rc yh_util_blink_device ( yh_session * session,
uint8_t seconds )

Blink the LED of the device to identify it

Parameters
sessionAuthenticated session to use
secondsNumber of seconds to blink
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. See yh_rc for other possible errors

Definition at line 3766 of file yubihsm.c.

3766 {
3767
3768 if (session == NULL) {
3771 }
3772
3773 yh_rc yrc;
3774
3775 uint8_t response[5];
3776 size_t response_len = sizeof(response);
3777 yh_cmd response_cmd;
3778
3779 yrc = yh_send_secure_msg(session, YHC_BLINK_DEVICE, &seconds, sizeof(seconds),
3780 &response_cmd, response, &response_len);
3781 if (yrc != YHR_SUCCESS) {
3782 DBG_ERR("Failed to send BLINK DEVICE command: %s", yh_strerror(yrc));
3783 return yrc;
3784 }
3785
3786 if (response_cmd == YHC_ERROR) {
3787 yh_rc translated = translate_device_error(response[0]);
3788 DBG_ERR("Unable to blink the device: %s (%x)", yh_strerror(translated),
3789 response[0]);
3790 return translated;
3791 }
3792
3793 return YHR_SUCCESS;
3794}
yh_rc yh_send_secure_msg(yh_session *session, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len)
Definition yubihsm.c:416
yh_cmd
Definition yubihsm.h:243
@ YHC_ERROR
Definition yubihsm.h:348
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_change_authentication_key()

yh_rc yh_util_change_authentication_key ( yh_session * session,
uint16_t * key_id,
const uint8_t * key_enc,
size_t key_enc_len,
const uint8_t * key_mac,
size_t key_mac_len )

Replace the long lived encryption key and MAC key associated with an YH_AUTHENTICATION_KEY in the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key to replace
key_encNew long lived encryption key
key_enc_lenLength of the new encryption key. Must be YH_KEY_LEN
key_macNew long lived MAC key
key_mac_lenLength of the new MAC key. Must be YH_KEY_LEN
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if key_enc_len or key_mac_len are not the expected values. See yh_rc for other possible errors
See also
Authentication Key

Definition at line 3094 of file yubihsm.c.

3098 {
3099
3100 if (session == NULL || key_id == NULL || key_enc == NULL ||
3101 key_enc_len != YH_KEY_LEN || key_mac == NULL ||
3102 key_mac_len != YH_KEY_LEN) {
3105 }
3106
3107#pragma pack(push, 1)
3108 union {
3109 struct {
3112 uint8_t key_enc[YH_KEY_LEN];
3113 uint8_t key_mac[YH_KEY_LEN];
3114 };
3115 uint8_t buf[1];
3116 } data;
3117 union {
3118 struct {
3120 };
3121 uint8_t buf[1];
3122 } response;
3123#pragma pack(pop)
3124 size_t response_len = sizeof(response);
3125 yh_cmd response_cmd;
3126
3127 data.key_id = htons(*key_id);
3128 data.algorithm = YH_ALGO_AES128_YUBICO_AUTHENTICATION;
3129 memcpy(data.key_enc, key_enc, key_enc_len);
3130 memcpy(data.key_mac, key_mac, key_mac_len);
3131
3132 yh_rc yrc = yh_send_secure_msg(session, YHC_CHANGE_AUTHENTICATION_KEY,
3133 data.buf, sizeof(data), &response_cmd,
3134 response.buf, &response_len);
3135 insecure_memzero(data.buf, sizeof(data));
3136 if (yrc != YHR_SUCCESS) {
3137 DBG_ERR("Failed to send CHANGE AUTHENTICATION KEY command: %s\n",
3138 yh_strerror(yrc));
3139 return yrc;
3140 }
3141
3142 if (response_cmd == YHC_ERROR) {
3143 yh_rc translated = translate_device_error(response.buf[0]);
3144 DBG_ERR("Unable to change authentication key: %s (%x)\n",
3145 yh_strerror(translated), response.buf[0]);
3146 return translated;
3147 }
3148
3149 *key_id = ntohs(response.key_id);
3150 DBG_INFO("Changed Authentication key 0x%04x", *key_id);
3151
3152 return YHR_SUCCESS;
3153}
@ YH_ALGO_AES128_YUBICO_AUTHENTICATION
aes128-yubico-authentication
Definition yubihsm.h:466
uint8_t buf[2048]
uint16_t key_id
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_change_authentication_key_derived()

yh_rc yh_util_change_authentication_key_derived ( yh_session * session,
uint16_t * key_id,
const uint8_t * password,
size_t password_len )

Replace the long lived encryption key and MAC key associated with an YH_AUTHENTICATION_KEY in the device with keys derived from a password

Parameters
sessionAuthenticated session to use
key_idObject ID of the key to replace
passwordPassword to derive the new encryption key and MAC key
password_lenLength of password
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors
See also
Authentication Key

Definition at line 3155 of file yubihsm.c.

3158 {
3159 if (session == NULL || key_id == NULL || password == NULL) {
3162 }
3163
3164 uint8_t key_enc[SCP_KEY_LEN];
3165 uint8_t key_mac[SCP_KEY_LEN];
3166
3167 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
3168
3169 if (yrc == YHR_SUCCESS) {
3171 sizeof(key_enc), key_mac,
3172 sizeof(key_mac));
3173 insecure_memzero(key_enc, sizeof(key_enc));
3174 insecure_memzero(key_mac, sizeof(key_mac));
3175 }
3176 return yrc;
3177}
yh_rc yh_util_change_authentication_key(yh_session *session, uint16_t *key_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)
Definition yubihsm.c:3094
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_close_session()

yh_rc yh_util_close_session ( yh_session * session)

Close a session

Parameters
sessionSession to close
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. See yh_rc for other possible errors

Definition at line 1257 of file yubihsm.c.

1257 {
1258
1259 if (session == NULL) {
1262 }
1263
1264 yh_rc yrc;
1265
1266 uint8_t response[5];
1267 size_t response_len = sizeof(response);
1268 yh_cmd response_cmd;
1269
1270 yrc = yh_send_secure_msg(session, YHC_CLOSE_SESSION, NULL, 0, &response_cmd,
1271 response, &response_len);
1272 if (yrc != YHR_SUCCESS) {
1273 DBG_ERR("Failed to send CLOSE SESSION command: %s", yh_strerror(yrc));
1274 return yrc;
1275 }
1276
1277 if (response_cmd == YHC_ERROR) {
1278 yh_rc translated = translate_device_error(response[0]);
1279 DBG_ERR("Unable to close session: %s (%x)", yh_strerror(translated),
1280 response[0]);
1281 return translated;
1282 }
1283
1284 return YHR_SUCCESS;
1285}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_create_otp_aead()

yh_rc yh_util_create_otp_aead ( yh_session * session,
uint16_t key_id,
const uint8_t * key,
const uint8_t * private_id,
uint8_t * out,
size_t * out_len )

Create a Yubico OTP AEAD using the provided data

Parameters
sessionAuthenticated session to use
key_idObject ID of the Otp-aead Key to use
keyOTP key
private_idOTP private id
outThe created AEAD
out_lenLength of the created AEAD
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 3179 of file yubihsm.c.

3181 {
3182
3183 if (session == NULL || key == NULL || private_id == NULL || out == NULL ||
3184 out_len == NULL) {
3187 }
3188#pragma pack(push, 1)
3189 union {
3190 struct {
3192 uint8_t key[16];
3193 uint8_t private_id[6];
3194 };
3195 uint8_t buf[1];
3196 } data;
3197#pragma pack(pop)
3198
3199 yh_cmd response_cmd;
3200
3201 data.key_id = htons(key_id);
3202 memcpy(data.key, key, sizeof(data.key));
3203 memcpy(data.private_id, private_id, sizeof(data.private_id));
3204
3205 yh_rc yrc = yh_send_secure_msg(session, YHC_CREATE_OTP_AEAD, data.buf,
3206 sizeof(data), &response_cmd, out, out_len);
3207 insecure_memzero(data.buf, sizeof(data));
3208 if (yrc != YHR_SUCCESS) {
3209 DBG_ERR("Failed to send CREATE OTP AEAD command: %s\n", yh_strerror(yrc));
3210 return yrc;
3211 }
3212
3213 if (response_cmd == YHC_ERROR) {
3214 yh_rc translated = translate_device_error(out[0]);
3215 DBG_ERR("Unable to get OTP AEAD: %s (%x)\n", yh_strerror(translated),
3216 out[0]);
3217 return translated;
3218 }
3219
3220 return YHR_SUCCESS;
3221}
size_t out_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_decrypt_oaep()

yh_rc yh_util_decrypt_oaep ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len,
const uint8_t * label,
size_t label_len,
yh_algorithm mgf1Algo )

Decrypt data using RSA-OAEP

Parameters
sessionAuthenticated session to use
key_idObject ID of the RSA key to use for decryption
inEncrypted data
in_lenLength of encrypted data. Must be 256, 384 or 512
outDecrypted data
out_lenLength of decrypted data
labelOAEP label
label_lenLength of OAEP label. Must be 20, 32, 48 or 64
mgf1AlgoMGF1 algorithm
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL. YHR_WRONG_LENGTH if in_len or label_len are not what expected. See yh_rc for other possible errors

Definition at line 2107 of file yubihsm.c.

2110 {
2111
2112 if (session == NULL || in == NULL || out == NULL || out_len == NULL ||
2113 label == NULL) {
2116 }
2117
2118#pragma pack(push, 1)
2119 union {
2120 struct {
2122 uint8_t mgf1Algo;
2124 };
2125 uint8_t buf[1];
2126 } data;
2127#pragma pack(pop)
2128
2129 yh_cmd response_cmd;
2130 yh_rc yrc;
2131 uint16_t len = 0;
2132
2133 data.key_id = htons(key_id);
2134 len += sizeof(data.key_id);
2135
2136 data.mgf1Algo = mgf1Algo;
2137 len += sizeof(data.mgf1Algo);
2138
2139 // in_len has to match the rsa key size
2140 if (in_len != 256 && in_len != 384 && in_len != 512) {
2141 DBG_ERR("Wrong input length");
2142 return YHR_WRONG_LENGTH;
2143 }
2144
2145 // label_len is hashed and specified the mgf hash
2146 if (label_len != 20 && label_len != 32 && label_len != 48 &&
2147 label_len != 64) {
2148 DBG_ERR("Wrong label length");
2149 return YHR_WRONG_LENGTH;
2150 }
2151
2152 memcpy(data.bytes, in, in_len);
2153 len += in_len;
2154 memcpy(data.bytes + in_len, label, label_len);
2155 len += label_len;
2156
2157 yrc = yh_send_secure_msg(session, YHC_DECRYPT_OAEP, data.buf, len,
2158 &response_cmd, out, out_len);
2159 if (yrc != YHR_SUCCESS) {
2160 DBG_ERR("Failed to send DECRYPT OAEP command: %s", yh_strerror(yrc));
2161 return yrc;
2162 }
2163
2164 if (response_cmd == YHC_ERROR) {
2165 yh_rc translated = translate_device_error(out[0]);
2166 DBG_ERR("Unable to get decrypted data: %s (%x)", yh_strerror(translated),
2167 out[0]);
2168 return translated;
2169 }
2170
2171 return YHR_SUCCESS;
2172}
vector< char > bytes
Definition types.hpp:243
#define YH_MSG_BUF_SIZE
Maximum length of message buffer.
Definition yubihsm.h:93
char * label
size_t len
size_t label_len
size_t in_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_decrypt_otp()

yh_rc yh_util_decrypt_otp ( yh_session * session,
uint16_t key_id,
const uint8_t * aead,
size_t aead_len,
const uint8_t * otp,
uint16_t * useCtr,
uint8_t * sessionCtr,
uint8_t * tstph,
uint16_t * tstpl )

Decrypt a Yubico OTP and return counters and time information.

Parameters
sessionAuthenticated session to use
key_idObject ID of the key used for decryption
aeadAEAD as created by yh_util_create_otp_aead() or yh_util_randomize_otp_aead()
aead_lenLength of AEAD
otpOTP
useCtrOTP use counter
sessionCtrOTP session counter
tstphOTP timestamp high
tstplOTP timestamp low
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 3261 of file yubihsm.c.

3265 {
3266
3267#pragma pack(push, 1)
3268 union {
3269 struct {
3271 uint8_t aead[6 + 16 + 6 + 8]; // FIXME: ya.. magic numbers!
3272 uint8_t otp[16];
3273 };
3274 uint8_t buf[1];
3275 } data;
3276 union {
3277 struct {
3278 uint16_t useCtr;
3279 uint8_t sessionCtr;
3280 uint8_t tstph;
3281 uint16_t tstpl;
3282 };
3283 uint8_t buf[1];
3284 } response;
3285#pragma pack(pop)
3286
3287 if (session == NULL || aead == NULL || otp == NULL ||
3288 aead_len != sizeof(data.aead)) {
3291 }
3292
3293 yh_cmd response_cmd;
3294 size_t response_len = sizeof(response);
3295
3296 data.key_id = htons(key_id);
3297 memcpy(data.aead, aead, sizeof(data.aead));
3298 memcpy(data.otp, otp, sizeof(data.otp));
3299
3300 yh_rc yrc =
3301 yh_send_secure_msg(session, YHC_DECRYPT_OTP, data.buf, sizeof(data),
3302 &response_cmd, response.buf, &response_len);
3303 insecure_memzero(data.buf, sizeof(data));
3304 if (yrc != YHR_SUCCESS) {
3305 DBG_ERR("Failed to send DECRYPT OTP command: %s\n", yh_strerror(yrc));
3306 return yrc;
3307 }
3308
3309 if (response_cmd == YHC_ERROR) {
3310 yh_rc translated = translate_device_error(response.buf[0]);
3311 DBG_ERR("Unable to decrypt OTP: %s (%x)\n", yh_strerror(translated),
3312 response.buf[0]);
3313 return translated;
3314 }
3315
3316 if (response_len != sizeof(response)) {
3317 DBG_ERR("Wrong size returned");
3318 return YHR_WRONG_LENGTH;
3319 }
3320
3321 if (useCtr) {
3322 *useCtr = response.useCtr;
3323 }
3324 if (sessionCtr) {
3325 *sessionCtr = response.sessionCtr;
3326 }
3327 if (tstph) {
3328 *tstph = response.tstph;
3329 }
3330 if (tstpl) {
3331 *tstpl = response.tstpl;
3332 }
3333
3334 return YHR_SUCCESS;
3335}
uint8_t otp[32]
Definition yubico_otp.c:49
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_decrypt_pkcs1v1_5()

yh_rc yh_util_decrypt_pkcs1v1_5 ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Decrypt data that was encrypted using RSA-PKCS#1v1.5

Parameters
sessionAuthenticated session to use
key_idObject ID of the RSA key to use for decryption
inEncrypted data
in_lenLength of encrypted data
outDecrypted data
out_lenLength of decrypted data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is bigger than YH_MSG_BUF_SIZE-2. See yh_rc for other possible errors

Definition at line 2059 of file yubihsm.c.

2061 {
2062
2063 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
2066 }
2067
2068 if (in_len > YH_MSG_BUF_SIZE - 2) {
2069 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
2071 }
2072
2073#pragma pack(push, 1)
2074 union {
2075 struct {
2078 };
2079 uint8_t buf[1];
2080 } data;
2081#pragma pack(pop)
2082
2083 yh_cmd response_cmd;
2084 yh_rc yrc;
2085
2086 data.key_id = htons(key_id);
2087
2088 memcpy(data.bytes, in, in_len);
2089
2090 yrc = yh_send_secure_msg(session, YHC_DECRYPT_PKCS1, data.buf, in_len + 2,
2091 &response_cmd, out, out_len);
2092 if (yrc != YHR_SUCCESS) {
2093 DBG_ERR("Failed to send DECRYPT PKCS1 command: %s", yh_strerror(yrc));
2094 return yrc;
2095 }
2096
2097 if (response_cmd == YHC_ERROR) {
2098 yh_rc translated = translate_device_error(out[0]);
2099 DBG_ERR("Unable to get decrypted data: %s (%x)", yh_strerror(translated),
2100 out[0]);
2101 return translated;
2102 }
2103
2104 return YHR_SUCCESS;
2105}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_delete_object()

yh_rc yh_util_delete_object ( yh_session * session,
uint16_t id,
yh_object_type type )

Delete an object in the device

Parameters
sessionAuthenticated session to use
idObject ID of the object to delete
typeType of object to delete. See yh_object_type
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if session is NULL. See yh_rc for other possible errors

Definition at line 2222 of file yubihsm.c.

2223 {
2224
2225 if (session == NULL) {
2228 }
2229
2230#pragma pack(push, 1)
2231 union {
2232 struct {
2233 uint16_t id;
2234 uint8_t type;
2235 };
2236 uint8_t buf[1];
2237 } data;
2238#pragma pack(pop)
2239
2240 yh_rc yrc;
2241 yh_cmd response_cmd;
2242 uint8_t response[YH_MSG_BUF_SIZE];
2243 size_t response_len = sizeof(response);
2244
2245 data.type = type;
2246 data.id = htons(id);
2247
2248 yrc = yh_send_secure_msg(session, YHC_DELETE_OBJECT, data.buf, sizeof(data),
2249 &response_cmd, response, &response_len);
2250 if (yrc != YHR_SUCCESS) {
2251 DBG_ERR("Failed to send DELETE command: %s", yh_strerror(yrc));
2252 return yrc;
2253 }
2254
2255 if (response_cmd == YHC_ERROR) {
2256 yh_rc translated = translate_device_error(response[0]);
2257 DBG_ERR("Unable to delete object: %s (%x)", yh_strerror(translated),
2258 response[0]);
2259 return translated;
2260 }
2261
2262 return YHR_SUCCESS;
2263}
uint64_t id
Definition code_cache.cpp:0
yh_object_type type
Definition yubihsm.h:672
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_derive_ecdh()

yh_rc yh_util_derive_ecdh ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Derive an ECDH key from a private EC key on the device and a provided public EC key

Parameters
sessionAuthenticated session to use
key_idObject ID of the EC private key to use for ECDH derivation
inPublic key of another EC key-pair
in_lenLength of public key
outShared secret ECDH key
out_lenLength of the shared ECDH key
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is bigger than YH_MSG_BUF_SIZE-2. See yh_rc for other possible errors

Definition at line 2174 of file yubihsm.c.

2176 {
2177
2178 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
2181 }
2182
2183 if (in_len > YH_MSG_BUF_SIZE - 2) {
2184 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
2186 }
2187
2188#pragma pack(push, 1)
2189 union {
2190 struct {
2193 };
2194 uint8_t buf[1];
2195 } data;
2196#pragma pack(pop)
2197
2198 yh_cmd response_cmd;
2199 yh_rc yrc;
2200
2201 data.key_id = htons(key_id);
2202
2203 memcpy(data.bytes, in, in_len);
2204
2205 yrc = yh_send_secure_msg(session, YHC_DERIVE_ECDH, data.buf, in_len + 2,
2206 &response_cmd, out, out_len);
2207 if (yrc != YHR_SUCCESS) {
2208 DBG_ERR("Failed to send DERIVE ECDH command: %s", yh_strerror(yrc));
2209 return yrc;
2210 }
2211
2212 if (response_cmd == YHC_ERROR) {
2213 yh_rc translated = translate_device_error(out[0]);
2214 DBG_ERR("Unable to get decrypted data: %s (%x)", yh_strerror(translated),
2215 out[0]);
2216 return translated;
2217 }
2218
2219 return YHR_SUCCESS;
2220}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_export_wrapped()

yh_rc yh_util_export_wrapped ( yh_session * session,
uint16_t wrapping_key_id,
yh_object_type target_type,
uint16_t target_id,
uint8_t * out,
size_t * out_len )

Export an object under wrap from the device

Parameters
sessionAuthenticated session to use
wrapping_key_idObject ID of the Wrap Key to use to wrap the object
target_typeType of the object to be exported. See yh_object_type
target_idObject ID of the object to be exported
outWrapped data
out_lenLength of wrapped data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 2265 of file yubihsm.c.

2267 {
2268
2269 if (session == NULL || out == NULL || out_len == NULL) {
2272 }
2273
2274#pragma pack(push, 1)
2275 union {
2276 struct {
2278 uint8_t type;
2279 uint16_t tgt_id;
2280 };
2281 uint8_t buf[1];
2282 } data;
2283#pragma pack(pop)
2284
2285 yh_cmd response_cmd;
2286 yh_rc yrc;
2287
2288 data.key_id = htons(wrapping_key_id);
2289 data.type = (uint8_t) target_type;
2290 data.tgt_id = htons(target_id);
2291
2292 yrc = yh_send_secure_msg(session, YHC_EXPORT_WRAPPED, data.buf, sizeof(data),
2293 &response_cmd, out, out_len);
2294 if (yrc != YHR_SUCCESS) {
2295 DBG_ERR("Failed to send EXPORT WRAPPED command: %s", yh_strerror(yrc));
2296 return yrc;
2297 }
2298
2299 if (response_cmd == YHC_ERROR) {
2300 yh_rc translated = translate_device_error(out[0]);
2301 DBG_ERR("Unable to get wrapped object: %s (%x)", yh_strerror(translated),
2302 out[0]);
2303 return translated;
2304 }
2305
2306 return YHR_SUCCESS;
2307}
yh_object_type target_type
uint16_t target_id
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_generate_ec_key()

yh_rc yh_util_generate_ec_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm )

Generate an Elliptic Curve key in the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm to use to generate the EC key. Supported algorithm: YH_ALGO_EC_P224, YH_ALGO_EC_P256, YH_ALGO_EC_K256, YH_ALGO_EC_BP256, YH_ALGO_EC_P384, YH_ALGO_EC_BP384, YH_ALGO_EC_BP512 and YH_ALGO_EC_P521.
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is not one of YH_ALGO_EC_P224, YH_ALGO_EC_P256, YH_ALGO_EC_K256, YH_ALGO_EC_BP256, YH_ALGO_EC_P384, YH_ALGO_EC_BP384, YH_ALGO_EC_BP512 or YH_ALGO_EC_P521. See yh_rc for other possible errors

Definition at line 1913 of file yubihsm.c.

1916 {
1917
1918 if (!yh_is_ec(algorithm)) {
1919 DBG_ERR("Invalid algorithm %d", algorithm);
1921 }
1922
1923 return generate_key(session, key_id, label, domains, capabilities, algorithm);
1924}
bool yh_is_ec(yh_algorithm algorithm)
Definition yubihsm.c:4260
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_generate_ed_key()

yh_rc yh_util_generate_ed_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm )

Generate an ED key in the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel for the key. Maximum length YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the ED key. See yh_string_to_capabilities()
algorithmAlgorithm to use to generate the ED key. Supported algorithm: YH_ALGO_EC_ED25519
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is not YH_ALGO_EC_ED25519. See yh_rc for other possible errors

Definition at line 1926 of file yubihsm.c.

1929 {
1930
1931 if (!yh_is_ed(algorithm)) {
1932 DBG_ERR("Invalid algorithm %d", algorithm);
1934 }
1935
1936 return generate_key(session, key_id, label, domains, capabilities, algorithm);
1937}
bool yh_is_ed(yh_algorithm algorithm)
Definition yubihsm.c:4280
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_generate_hmac_key()

yh_rc yh_util_generate_hmac_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm )

Generate an HMAC key in the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm to use to generate the HMAC key. Supported algorithims: YH_ALGO_HMAC_SHA1, YH_ALGO_HMAC_SHA256, YH_ALGO_HMAC_SHA384 and YH_ALGO_HMAC_SHA512
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL. See yh_rc for other possible errors

Definition at line 1992 of file yubihsm.c.

1995 {
1996
1997 if (session == NULL || label == NULL || strlen(label) > YH_OBJ_LABEL_LEN ||
1998 key_id == NULL) {
2001 }
2002
2003 yh_rc yrc;
2004
2005#pragma pack(push, 1)
2006 union {
2007 struct {
2013 };
2014 uint8_t buf[1];
2015 } data;
2016 union {
2017 struct {
2019 };
2020 uint8_t buf[1];
2021 } response;
2022#pragma pack(pop)
2023
2024 size_t response_len = sizeof(response);
2025 yh_cmd response_cmd;
2026
2027 data.key_id = htons(*key_id);
2028
2029 memcpy(data.label, label, strlen(label));
2030 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2031
2032 data.domains = htons(domains);
2033
2034 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2035
2036 data.algorithm = algorithm;
2037
2038 yrc =
2039 yh_send_secure_msg(session, YHC_GENERATE_HMAC_KEY, data.buf, sizeof(data),
2040 &response_cmd, response.buf, &response_len);
2041 if (yrc != YHR_SUCCESS) {
2042 DBG_ERR("Failed to send GENERATE HMAC command: %s", yh_strerror(yrc));
2043 return yrc;
2044 }
2045
2046 if (response_cmd == YHC_ERROR) {
2047 yh_rc translated = translate_device_error(response.buf[0]);
2048 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
2049 response.buf[0]);
2050 return translated;
2051 }
2052
2053 *key_id = ntohs(response.key_id);
2054 DBG_INFO("Generated HMAC key 0x%04x", *key_id);
2055
2056 return YHR_SUCCESS;
2057}
#define YH_OBJ_LABEL_LEN
Max length of object labels.
Definition yubihsm.h:123
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_generate_otp_aead_key()

yh_rc yh_util_generate_otp_aead_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
uint32_t nonce_id )

Generate an YH_OTP_AEAD_KEY for Yubico OTP decryption in the device.

Parameters
sessionAuthenticated session to use
key_idObject ID of the AEAD Key. 0 if the Object ID should be generated by the device
labelLabel of the AEAD Key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains the AEAD Key will be operating within. See yh_string_to_domains()
capabilitiesCapabilities of the AEAD Key. See yh_string_to_capabilities()
algorithmAlgorithm used to generate the AEAD Key. Supported algorithms: YH_ALGO_AES128_YUBICO_OTP, YH_ALGO_AES192_YUBICO_OTP and YH_ALGO_AES256_YUBICO_OTP
nonce_idNonce ID
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 3422 of file yubihsm.c.

3425 {
3426
3427 if (session == NULL || key_id == NULL || label == NULL ||
3428 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL) {
3431 }
3432
3433 yh_rc yrc;
3434
3435#pragma pack(push, 1)
3436 union {
3437 struct {
3443 uint32_t nonce_id;
3444 };
3445 uint8_t buf[1];
3446 } data;
3447 uint16_t data_len = sizeof(data);
3448 union {
3449 struct {
3451 };
3452 uint8_t buf[1];
3453 } response;
3454#pragma pack(pop)
3455
3456 size_t response_len = sizeof(response);
3457 yh_cmd response_cmd;
3458
3459 data.key_id = htons(*key_id);
3460
3461 memcpy(data.label, label, strlen(label));
3462 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
3463
3464 data.domains = htons(domains);
3465
3466 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
3467
3468 data.algorithm = algorithm;
3469
3470 data.nonce_id = nonce_id;
3471
3472 yrc =
3473 yh_send_secure_msg(session, YHC_GENERATE_OTP_AEAD_KEY, data.buf, data_len,
3474 &response_cmd, response.buf, &response_len);
3475 insecure_memzero(data.buf, data_len);
3476 if (yrc != YHR_SUCCESS) {
3477 DBG_ERR("Failed to send GENERATE OTP AEAD KEY command: %s",
3478 yh_strerror(yrc));
3479 return yrc;
3480 }
3481
3482 if (response_cmd == YHC_ERROR) {
3483 yh_rc translated = translate_device_error(response.buf[0]);
3484 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
3485 response.buf[0]);
3486 return translated;
3487 }
3488
3489 *key_id = ntohs(response.key_id);
3490 DBG_INFO("Generated OTP AEAD key 0x%04x\n", *key_id);
3491
3492 return YHR_SUCCESS;
3493}
unsigned int uint32_t
Definition stdint.h:126
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_generate_rsa_key()

yh_rc yh_util_generate_rsa_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm )

Generate an RSA key in the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm to use to generate the RSA key. Supported algorithms: YH_ALGO_RSA_2048, YH_ALGO_RSA_3072 and YH_ALGO_RSA_4096
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is not one of YH_ALGO_RSA_2048, YH_ALGO_RSA_3072 or YH_ALGO_RSA_4096. See yh_rc for other possible errors

Definition at line 1900 of file yubihsm.c.

1903 {
1904
1905 if (!yh_is_rsa(algorithm)) {
1906 DBG_ERR("Invalid algorithm %d", algorithm);
1908 }
1909
1910 return generate_key(session, key_id, label, domains, capabilities, algorithm);
1911}
bool yh_is_rsa(yh_algorithm algorithm)
Definition yubihsm.c:4245
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_generate_wrap_key()

yh_rc yh_util_generate_wrap_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const yh_capabilities * delegated_capabilities )

Generate a Wrap Key that can be used for export, import, wrap data and unwrap data in the device.

Parameters
sessionAuthenticated session to use
key_idObject ID of the Wrap Key. 0 if the Object ID should be generated by the device
labelLabel of the Wrap Key. Maximum length YH_OBJ_LABEL_LEN
domainsDomains where the Wrap Key will be operating within. See yh_string_to_domains()
capabilitiesCapabilities of the Wrap Key. See yh_string_to_capabilities()
algorithmAlgorithm used to generate the Wrap Key
delegated_capabilitiesDelegated capabilitites of the Wrap Key. See yh_string_to_capabilities()
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors
See also
yh_object_type

Definition at line 2458 of file yubihsm.c.

2462 {
2463
2464 if (session == NULL || key_id == NULL || label == NULL ||
2465 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
2466 delegated_capabilities == NULL) {
2469 }
2470
2471 yh_rc yrc;
2472
2473#pragma pack(push, 1)
2474 union {
2475 struct {
2482 };
2483 uint8_t buf[1];
2484 } data;
2485 uint16_t data_len = sizeof(data);
2486 union {
2487 struct {
2489 };
2490 uint8_t buf[1];
2491 } response;
2492#pragma pack(pop)
2493
2494 size_t response_len = sizeof(response);
2495 yh_cmd response_cmd;
2496
2497 data.key_id = htons(*key_id);
2498
2499 memcpy(data.label, label, strlen(label));
2500 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2501
2502 data.domains = htons(domains);
2503
2504 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2505
2506 data.algorithm = algorithm;
2507
2508 memcpy(data.delegated_capabilities, delegated_capabilities,
2510
2511 yrc = yh_send_secure_msg(session, YHC_GENERATE_WRAP_KEY, data.buf, data_len,
2512 &response_cmd, response.buf, &response_len);
2513 if (yrc != YHR_SUCCESS) {
2514 DBG_ERR("Failed to send GENERATE WRAP KEY command: %s", yh_strerror(yrc));
2515 return yrc;
2516 }
2517
2518 if (response_cmd == YHC_ERROR) {
2519 yh_rc translated = translate_device_error(response.buf[0]);
2520 DBG_ERR("Unable to generate key: %s (%x)", yh_strerror(translated),
2521 response.buf[0]);
2522 return translated;
2523 }
2524
2525 *key_id = ntohs(response.key_id);
2526 DBG_INFO("Generated Wrap key 0x%04x\n", *key_id);
2527
2528 return YHR_SUCCESS;
2529}
yh_capabilities delegated_capabilities
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_device_info()

yh_rc yh_util_get_device_info ( yh_connector * connector,
uint8_t * major,
uint8_t * minor,
uint8_t * patch,
uint32_t * serial,
uint8_t * log_total,
uint8_t * log_used,
yh_algorithm * algorithms,
size_t * n_algorithms )

Get device version, device serial number, supported algorithms and available log entries.

Parameters
connectorConnector to the device
majorDevice major version number
minorDevice minor version number
patchDevice build version number
serialDevice serial number
log_totalTotal number of log entries
log_usedNumber of written log entries
algorithmsList of supported algorithms
n_algorithmsNumber of supported algorithms
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the connector is NULL. YHR_BUFFER_TOO_SMALL if n_algorithms is smaller than the number of actually supported algorithms. See yh_rc for other possible errors.
See also
Algorithms

Definition at line 938 of file yubihsm.c.

941 {
942
943 if (connector == NULL) {
946 }
947
948 yh_rc yrc;
949
950#pragma pack(push, 1)
951 union {
952 struct {
957 uint8_t log_total;
958 uint8_t log_used;
960 };
961 uint8_t buf[1];
962 } response;
963#pragma pack(pop)
964 size_t response_len = sizeof(response);
965 yh_cmd response_cmd;
966
967 yrc = yh_send_plain_msg(connector, YHC_GET_DEVICE_INFO, NULL, 0,
968 &response_cmd, response.buf, &response_len);
969 if (yrc != YHR_SUCCESS) {
970 DBG_ERR("Failed to send GET DEVICE INFO command: %s", yh_strerror(yrc));
971 return yrc;
972 }
973
974 if (response_cmd == YHC_ERROR) {
975 yh_rc translated = translate_device_error(response.buf[0]);
976 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated),
977 response.buf[0]);
978 return translated;
979 }
980
981 if (major != NULL) {
982 *major = response.major;
983 }
984
985 if (minor != NULL) {
986 *minor = response.minor;
987 }
988
989 if (patch != NULL) {
990 *patch = response.patch;
991 }
992
993 if (serial != NULL) {
994 *serial = ntohl(response.serial);
995 }
996
997 if (log_total != NULL) {
998 *log_total = response.log_total;
999 }
1000
1001 if (log_used != NULL) {
1002 *log_used = response.log_used;
1003 }
1004
1005 if (algorithms != NULL && n_algorithms) {
1006 size_t items = response_len - sizeof(response.major) -
1007 sizeof(response.minor) - sizeof(response.patch) -
1008 sizeof(response.serial) - sizeof(response.log_total) -
1009 sizeof(response.log_used);
1010 if (*n_algorithms < items) {
1011 DBG_ERR("Algorithms buffer too small");
1012 return YHR_BUFFER_TOO_SMALL;
1013 }
1014 for (size_t i = 0; i < items; i++) {
1015 algorithms[i] = response.algorithms[i];
1016 }
1017 *n_algorithms = items;
1018 }
1019
1020 return YHR_SUCCESS;
1021}
yh_rc yh_send_plain_msg(yh_connector *connector, yh_cmd cmd, const uint8_t *data, size_t data_len, yh_cmd *response_cmd, uint8_t *response, size_t *response_len)
Definition yubihsm.c:126
#define YH_MAX_ALGORITHM_COUNT
Max number of algorithms defined here.
Definition yubihsm.h:383
uint32_t serial
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_log_entries()

yh_rc yh_util_get_log_entries ( yh_session * session,
uint16_t * unlogged_boot,
uint16_t * unlogged_auth,
yh_log_entry * out,
size_t * n_items )

Get audit logs from the device.

When audit enforce is set, if the log buffer is full, no new operations (other than authentication operations) can be performed unless the log entries are read by this command and then the log index is set by calling yh_util_set_log_index().

Parameters
sessionAuthenticated session to use
unlogged_bootNumber of unlogged boot events. Used if the log buffer is full and audit enforce is set
unlogged_authNumber of unlogged authentication events. Used if the log buffer is full and audit enforce is set
outLog entries on the device
n_itemsNumber of log entries
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_BUFFER_TOO_SMALL if n_items is smaller than the actual number of retrieved log entries. See yh_rc for other possible errors

Definition at line 2531 of file yubihsm.c.

2533 {
2534
2535 if (session == NULL || out == NULL || n_items == NULL) {
2538 }
2539
2540 yh_rc yrc;
2541
2542 union {
2543 struct {
2544 uint16_t log_overflow_boot;
2545 uint16_t log_overflow_auth;
2546 uint8_t items;
2547 uint8_t data[1];
2548 };
2550 } response;
2551 size_t response_len = sizeof(response);
2552 yh_cmd response_cmd;
2553
2554 yrc = yh_send_secure_msg(session, YHC_GET_LOG_ENTRIES, NULL, 0, &response_cmd,
2555 response.buf, &response_len);
2556 if (yrc != YHR_SUCCESS) {
2557 DBG_ERR("Failed to send GET LOGS command: %s", yh_strerror(yrc));
2558 return yrc;
2559 }
2560
2561 if (response_cmd == YHC_ERROR) {
2562 yh_rc translated = translate_device_error(response.buf[0]);
2563 DBG_ERR("Unable to get logs: %s (%x)", yh_strerror(translated),
2564 response.buf[0]);
2565 return translated;
2566 }
2567
2568 if (unlogged_boot) {
2569 *unlogged_boot = ntohs(response.log_overflow_boot);
2570 }
2571
2572 if (unlogged_auth) {
2573 *unlogged_auth = ntohs(response.log_overflow_auth);
2574 }
2575
2576 if (response.items > YH_MAX_LOG_ENTRIES) {
2577 DBG_ERR(
2578 "Response contain more items than the maximum number of log entries");
2580 }
2581
2582 if (response.items > *n_items) {
2583 DBG_ERR("Log buffer too small, needed at lest %d, got %zu", response.items,
2584 *n_items);
2585 return YHR_BUFFER_TOO_SMALL;
2586 }
2587
2588 *n_items = response.items;
2589
2590 yh_log_entry *ptr = (yh_log_entry *) response.data;
2591 for (uint16_t i = 0; i < *n_items; i++) {
2592 out[i].number = ntohs(ptr[i].number);
2593 out[i].command = ptr[i].command;
2594 out[i].length = ntohs(ptr[i].length);
2595 out[i].session_key = ntohs(ptr[i].session_key);
2596 out[i].target_key = ntohs(ptr[i].target_key);
2597 out[i].second_key = ntohs(ptr[i].second_key);
2598 out[i].result = ptr[i].result;
2599 out[i].systick = ntohl(ptr[i].systick);
2600 memcpy(out[i].digest, ptr[i].digest, YH_LOG_DIGEST_SIZE);
2601 }
2602
2603 return YHR_SUCCESS;
2604}
Definition yubihsm.h:516
#define YH_LOG_DIGEST_SIZE
Size that the log digest is truncated to.
Definition yubihsm.h:127
#define YH_MAX_LOG_ENTRIES
Max log entries the device may hold.
Definition yubihsm.h:121
@ YHR_DEVICE_INVALID_DATA
Returned value when the device receives a malformed command invalid data.
Definition yubihsm.h:199
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_object_info()

yh_rc yh_util_get_object_info ( yh_session * session,
uint16_t id,
yh_object_type type,
yh_object_descriptor * object )

Get metadata of the object with the specified Object ID and Type

Parameters
sessionAuthenticated session to use
idObject ID of the object to get
typeObject type. See yh_object_type
objectObject information
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. See yh_rc for other possible errors.
See also
Objects

Definition at line 1128 of file yubihsm.c.

1130 {
1131
1132 if (session == NULL) {
1135 }
1136
1137 uint8_t data[3];
1138 uint8_t *dataptr = data;
1139
1140#pragma pack(push, 1)
1141 union {
1142 struct {
1144 uint16_t id;
1145 uint16_t len;
1147 uint8_t type;
1149 uint8_t sequence;
1150 uint8_t origin;
1153 };
1154 uint8_t buf[1];
1155 } response;
1156 size_t response_len = sizeof(response);
1157#pragma pack(pop)
1158
1159 yh_rc yrc;
1160 yh_cmd response_cmd;
1161
1162 *dataptr++ = id >> 8 & 0xff;
1163 *dataptr++ = id & 0xff;
1164
1165 *dataptr++ = (uint16_t) type;
1166
1167 yrc = yh_send_secure_msg(session, YHC_GET_OBJECT_INFO, data, sizeof(data),
1168 &response_cmd, response.buf, &response_len);
1169 if (yrc != YHR_SUCCESS) {
1170 DBG_ERR("Failed to send GET OBJECT INFO command: %s", yh_strerror(yrc));
1171 return yrc;
1172 }
1173
1174 if (response_cmd == YHC_ERROR) {
1175 yh_rc translated = translate_device_error(response.buf[0]);
1176 DBG_ERR("Unable to get object info: %s (%x)", yh_strerror(translated),
1177 response.buf[0]);
1178 return translated;
1179 }
1180
1181 if (response_len == sizeof(response)) {
1182 if (object) {
1183 memcpy(object->capabilities.capabilities, response.capabilities,
1185
1186 object->id = htons(response.id);
1187
1188 object->len = htons(response.len);
1189
1190 object->domains = htons(response.domains);
1191
1192 object->type = response.type;
1193
1194 object->algorithm = response.algorithm;
1195
1196 object->sequence = response.sequence;
1197
1198 object->origin = response.origin;
1199
1200 memcpy(object->label, response.label, YH_OBJ_LABEL_LEN);
1201 object->label[YH_OBJ_LABEL_LEN] = 0;
1202
1204 response.delegated_capabilities, YH_CAPABILITIES_LEN);
1205 }
1206 } else {
1207 DBG_ERR("Wrong response length, expecting %lu or 0, received %lu",
1208 (unsigned long) sizeof(yh_object_descriptor),
1209 (unsigned long) response_len);
1210 return YHR_WRONG_LENGTH;
1211 }
1212
1213 return YHR_SUCCESS;
1214}
yh_capabilities capabilities
Object capabilities.
Definition yubihsm.h:542
yh_capabilities delegated_capabilities
Object delegated capabilities.
Definition yubihsm.h:560
char label[YH_OBJ_LABEL_LEN+1]
Object label.
Definition yubihsm.h:558
yh_object_descriptor object
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_opaque()

yh_rc yh_util_get_opaque ( yh_session * session,
uint16_t object_id,
uint8_t * out,
size_t * out_len )

Get an YH_OPAQUE object (like an X.509 certificate) from the device

Parameters
sessionAuthenticated session to use
object_idObject ID of the Opaque object
outthe retrieved Opaque object
out_lenLength of the retrieved Opaque object
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 2636 of file yubihsm.c.

2637 {
2638
2639 if (session == NULL || out == NULL || out_len == NULL) {
2642 }
2643
2644 uint8_t data[2];
2645 yh_cmd response_cmd;
2646 yh_rc yrc;
2647
2648 uint16_t object_id_h = htons(object_id);
2649 memcpy(data, &object_id_h, sizeof(object_id_h));
2650 yrc = yh_send_secure_msg(session, YHC_GET_OPAQUE, data, sizeof(data),
2651 &response_cmd, out, out_len);
2652 if (yrc != YHR_SUCCESS) {
2653 DBG_ERR("Failed to send GET OPAQUE command: %s", yh_strerror(yrc));
2654 return yrc;
2655 }
2656
2657 if (response_cmd == YHC_ERROR) {
2658 yh_rc translated = translate_device_error(out[0]);
2659 DBG_ERR("Unable to get object: %s (%x)", yh_strerror(translated), out[0]);
2660 return translated;
2661 }
2662
2663 return YHR_SUCCESS;
2664}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_option()

yh_rc yh_util_get_option ( yh_session * session,
yh_option option,
uint8_t * out,
size_t * out_len )

Get a device-global option

Parameters
sessionAuthenticated session to use
optionOption to get. See yh_option
outOption value
out_lenLength of option value
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 3584 of file yubihsm.c.

3585 {
3586
3587 if (session == NULL || out == NULL || out_len == NULL) {
3590 }
3591 uint8_t buf[1] = {option};
3592 yh_cmd response_cmd;
3593
3594 yh_rc yrc = yh_send_secure_msg(session, YHC_GET_OPTION, buf, sizeof(buf),
3595 &response_cmd, out, out_len);
3596 if (yrc != YHR_SUCCESS) {
3597 DBG_ERR("Failed to send GET OPTION command: %s\n", yh_strerror(yrc));
3598 return yrc;
3599 }
3600
3601 if (response_cmd == YHC_ERROR) {
3602 yh_rc translated = translate_device_error(out[0]);
3603 DBG_ERR("Unable to get option: %s (%x)\n", yh_strerror(translated), out[0]);
3604 return translated;
3605 }
3606
3607 return YHR_SUCCESS;
3608}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_pseudo_random()

yh_rc yh_util_get_pseudo_random ( yh_session * session,
size_t len,
uint8_t * out,
size_t * out_len )

Get a fixed number of pseudo-random bytes from the device

Parameters
sessionAuthenticated session to use
lenLength of pseudo-random data to get
outPseudo-random data out
out_lenLength of pseudo-random data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL. See yh_rc for other possible errors

Definition at line 1560 of file yubihsm.c.

1561 {
1562 yh_rc yrc;
1563 yh_cmd response_cmd;
1564
1565 if (session == NULL || out == NULL || out_len == NULL) {
1568 }
1569
1570 union {
1571 uint16_t len;
1572 uint8_t buf[2];
1573 } data;
1574 data.len = htons(len);
1575
1576 yrc = yh_send_secure_msg(session, YHC_GET_PSEUDO_RANDOM, data.buf,
1577 sizeof(data), &response_cmd, out, out_len);
1578 if (yrc != YHR_SUCCESS) {
1579 DBG_ERR("Failed to send GET PSEUDO RANDOM command: %s", yh_strerror(yrc));
1580 return yrc;
1581 }
1582
1583 if (response_cmd == YHC_ERROR) {
1584 yh_rc translated = translate_device_error(out[0]);
1585 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated), out[0]);
1586 return translated;
1587 }
1588
1589 return yrc;
1590}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_public_key()

yh_rc yh_util_get_public_key ( yh_session * session,
uint16_t id,
uint8_t * data,
size_t * data_len,
yh_algorithm * algorithm )

Get the value of the public key with the specified Object ID

Parameters
sessionAuthenticated session to use
idObject ID of the public key
dataValue of the public key
data_lenLength of the public key in bytes
algorithmAlgorithm of the key
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_BUFFER_TOO_SMALL if the actual key length was bigger than data_len. See yh_rc for other possible errors

Definition at line 1216 of file yubihsm.c.

1217 {
1218
1219 if (session == NULL || data == NULL || data_len == NULL) {
1222 }
1223
1224 uint8_t cmd[2] = {id >> 8, id & 0xff};
1225 yh_cmd response_cmd;
1226 uint8_t response[YH_MSG_BUF_SIZE];
1227 size_t response_len = sizeof(response);
1228
1229 yh_rc yrc = yh_send_secure_msg(session, YHC_GET_PUBLIC_KEY, cmd, sizeof(cmd),
1230 &response_cmd, response, &response_len);
1231
1232 if (yrc != YHR_SUCCESS) {
1233 DBG_ERR("Failed to send GET PUBLIC KEY command: %s", yh_strerror(yrc));
1234 return yrc;
1235 }
1236
1237 if (response_cmd == YHC_ERROR) {
1238 yh_rc translated = translate_device_error(response[0]);
1239 DBG_ERR("Unable to get public key: %s (%x)", yh_strerror(translated),
1240 response[0]);
1241 return translated;
1242 }
1243
1244 if (response_len > *data_len) {
1245 return YHR_BUFFER_TOO_SMALL;
1246 }
1247
1248 if (algorithm) {
1249 *algorithm = *response;
1250 }
1251 *data_len = response_len - 1;
1252 memcpy(data, response + 1, *data_len);
1253
1254 return YHR_SUCCESS;
1255}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_storage_info()

yh_rc yh_util_get_storage_info ( yh_session * session,
uint16_t * total_records,
uint16_t * free_records,
uint16_t * total_pages,
uint16_t * free_pages,
uint16_t * page_size )

Report currently free storage. This is reported as free records, free pages and page size.

Parameters
sessionAuthenticated session to use
total_recordsTotal number of records
free_recordsNumber of free records
total_pagesTotal number of pages
free_pagesNumber of free pages
page_sizePage size in bytes
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. See yh_rc for other possible errors

Definition at line 3610 of file yubihsm.c.

3612 {
3613
3614 if (session == NULL) {
3617 }
3618
3619 yh_cmd response_cmd;
3620#pragma pack(push, 1)
3621 union {
3622 struct {
3623 uint16_t total_records;
3624 uint16_t free_records;
3625 uint16_t total_pages;
3626 uint16_t free_pages;
3628 };
3629 uint8_t buf[1];
3630 } response;
3631#pragma pack(pop)
3632 size_t response_len = sizeof(response);
3633
3634 yh_rc yrc = yh_send_secure_msg(session, YHC_GET_STORAGE_INFO, NULL, 0,
3635 &response_cmd, response.buf, &response_len);
3636 if (yrc != YHR_SUCCESS) {
3637 DBG_ERR("Failed to send GET STORAGE INFO command: %s\n", yh_strerror(yrc));
3638 return yrc;
3639 }
3640
3641 if (response_cmd == YHC_ERROR) {
3642 yh_rc translated = translate_device_error(response.buf[0]);
3643 DBG_ERR("Unable to get storage stats: %s (%x)\n", yh_strerror(translated),
3644 response.buf[0]);
3645 return translated;
3646 }
3647
3648 if (total_records) {
3649 *total_records = ntohs(response.total_records);
3650 }
3651 if (free_records) {
3652 *free_records = ntohs(response.free_records);
3653 }
3654 if (total_pages) {
3655 *total_pages = ntohs(response.total_pages);
3656 }
3657 if (free_pages) {
3658 *free_pages = ntohs(response.free_pages);
3659 }
3660 if (page_size) {
3661 *page_size = ntohs(response.page_size);
3662 }
3663
3664 return YHR_SUCCESS;
3665}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_get_template()

yh_rc yh_util_get_template ( yh_session * session,
uint16_t object_id,
uint8_t * out,
size_t * out_len )

Get a YH_TEMPLATE object from the device

Parameters
sessionAuthenticated session to use
object_idObject ID of the Template to get
outThe retrieved Template
out_lenLength of the retrieved Template
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 2805 of file yubihsm.c.

2806 {
2807 if (session == NULL || out == NULL) {
2810 }
2811
2812 uint8_t data[2];
2813 yh_cmd response_cmd;
2814 yh_rc yrc;
2815
2816 uint16_t object_id_h = htons(object_id);
2817 memcpy(data, &object_id_h, sizeof(object_id_h));
2818 yrc = yh_send_secure_msg(session, YHC_GET_TEMPLATE, data, sizeof(data),
2819 &response_cmd, out, out_len);
2820 if (yrc != YHR_SUCCESS) {
2821 DBG_ERR("Failed to send GET TEMPLATE command: %s", yh_strerror(yrc));
2822 return yrc;
2823 }
2824
2825 if (response_cmd == YHC_ERROR) {
2826 yh_rc translated = translate_device_error(out[0]);
2827 DBG_ERR("Unable to get template object: %s (%x)", yh_strerror(translated),
2828 out[0]);
2829 return translated;
2830 }
2831
2832 return YHR_SUCCESS;
2833}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_authentication_key()

yh_rc yh_util_import_authentication_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
const yh_capabilities * delegated_capabilities,
const uint8_t * key_enc,
size_t key_enc_len,
const uint8_t * key_mac,
size_t key_mac_len )

Import an YH_AUTHENTICATION_KEY into the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the imported key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
delegated_capabilitiesDelegated capabilities of the key. See yh_string_to_capabilities()
key_encLong lived encryption key of the Authentication Key to import
key_enc_lenLength of the encryption key. Must be YH_KEY_LEN
key_macLong lived MAC key of the Authentication Key to import
key_mac_lenLength of the MAC key. Must be YH_KEY_LEN
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if key_enc_len or key_mac_len are not the expected values. See yh_rc for other possible errors
See also
Authentication Key

Definition at line 2985 of file yubihsm.c.

2989 {
2990
2991 if (session == NULL || key_id == NULL || label == NULL ||
2992 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
2993 delegated_capabilities == NULL || key_enc == NULL ||
2994 key_enc_len != YH_KEY_LEN || key_mac == NULL ||
2995 key_mac_len != YH_KEY_LEN) {
2998 }
2999
3000#pragma pack(push, 1)
3001 union {
3002 struct {
3009 uint8_t key_enc[YH_KEY_LEN];
3010 uint8_t key_mac[YH_KEY_LEN];
3011 };
3012 uint8_t buf[1];
3013 } data;
3014 union {
3015 struct {
3017 };
3018 uint8_t buf[1];
3019 } response;
3020#pragma pack(pop)
3021 size_t response_len = sizeof(response);
3022 yh_cmd response_cmd;
3023
3024 memcpy(data.key_enc, key_enc, YH_KEY_LEN);
3025 memcpy(data.key_mac, key_mac, YH_KEY_LEN);
3026
3027 data.key_id = htons(*key_id);
3028
3029 memcpy(data.label, label, strlen(label));
3030 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
3031
3032 data.domains = htons(domains);
3033
3034 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
3035
3036 data.algorithm = YH_ALGO_AES128_YUBICO_AUTHENTICATION;
3037
3038 memcpy(data.delegated_capabilities, delegated_capabilities,
3040
3041 yh_rc yrc = yh_send_secure_msg(session, YHC_PUT_AUTHENTICATION_KEY, data.buf,
3042 sizeof(data), &response_cmd, response.buf,
3043 &response_len);
3044 insecure_memzero(data.buf, sizeof(data));
3045 if (yrc != YHR_SUCCESS) {
3046 DBG_ERR("Failed to send PUT AUTHENTICATION KEY command: %s\n",
3047 yh_strerror(yrc));
3048 return yrc;
3049 }
3050
3051 if (response_cmd == YHC_ERROR) {
3052 yh_rc translated = translate_device_error(response.buf[0]);
3053 DBG_ERR("Unable to store authentication key: %s (%x)\n",
3054 yh_strerror(translated), response.buf[0]);
3055 return translated;
3056 }
3057
3058 *key_id = ntohs(response.key_id);
3059 DBG_INFO("Stored Authentication key 0x%04x", *key_id);
3060
3061 return YHR_SUCCESS;
3062}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_authentication_key_derived()

yh_rc yh_util_import_authentication_key_derived ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
const yh_capabilities * delegated_capabilities,
const uint8_t * password,
size_t password_len )

Import an YH_AUTHENTICATION_KEY with long lived keys derived from a password

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
delegated_capabilitiesDelegated capabilities of the key. See yh_string_to_capabilities()
passwordPassword used to derive the long lived encryption key and MAC key of the Athentication Key
password_lenLength of password
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors
See also
Authentication Key

Definition at line 3064 of file yubihsm.c.

3068 {
3069
3070 if (session == NULL || key_id == NULL || label == NULL ||
3071 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
3072 delegated_capabilities == NULL || password == NULL) {
3075 }
3076
3077 uint8_t key_enc[SCP_KEY_LEN];
3078 uint8_t key_mac[SCP_KEY_LEN];
3079
3080 yh_rc yrc = derive_keys(password, password_len, key_enc, key_mac);
3081
3082 if (yrc == YHR_SUCCESS) {
3083 yrc =
3086 key_enc, sizeof(key_enc), key_mac,
3087 sizeof(key_mac));
3088 insecure_memzero(key_enc, sizeof(key_enc));
3089 insecure_memzero(key_mac, sizeof(key_mac));
3090 }
3091 return yrc;
3092}
yh_rc yh_util_import_authentication_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)
Definition yubihsm.c:2985
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_ec_key()

yh_rc yh_util_import_ec_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const uint8_t * s )

Import an Elliptic Curve key into the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs specified as an unsigned int. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm of the key to import. Must be one of: YH_ALGO_EC_P224, YH_ALGO_EC_P256, YH_ALGO_EC_K256, YH_ALGO_EC_BP256, YH_ALGO_EC_P384, YH_ALGO_EC_BP384, YH_ALGO_EC_BP512 or YH_ALGO_EC_P521
sthe EC key to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is not one of YH_ALGO_EC_P224, YH_ALGO_EC_P256, YH_ALGO_EC_K256, YH_ALGO_EC_BP256, YH_ALGO_EC_P384, YH_ALGO_EC_BP384, YH_ALGO_EC_BP512 or YH_ALGO_EC_P521. See yh_rc for other possible errors

Definition at line 1689 of file yubihsm.c.

1692 {
1693
1694 if (session == NULL || key_id == NULL || label == NULL ||
1695 strlen(label) > YH_OBJ_LABEL_LEN || s == NULL) {
1698 }
1699
1700 uint16_t component_len;
1701 switch (algorithm) {
1702 case YH_ALGO_EC_P224:
1703 component_len = 28;
1704 break;
1705 case YH_ALGO_EC_P256:
1706 case YH_ALGO_EC_K256:
1707 case YH_ALGO_EC_BP256:
1708 component_len = 32;
1709 break;
1710 case YH_ALGO_EC_P384:
1711 case YH_ALGO_EC_BP384:
1712 component_len = 48;
1713 break;
1714 case YH_ALGO_EC_BP512:
1715 component_len = 64;
1716 break;
1717 case YH_ALGO_EC_P521:
1718 component_len = 66;
1719 break;
1720 default:
1722 }
1723 return import_asymmetric(session, key_id, label, domains, capabilities,
1724 algorithm, s, component_len);
1725}
char * s
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_ed_key()

yh_rc yh_util_import_ed_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const uint8_t * k )

Import an ED key into the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key will have. 0 if the Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm of the key to import. Must be YH_ALGO_EC_ED25519
kthe ED key to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is not YH_ALGO_EC_ED25519. See yh_rc for other possible errors

Definition at line 1727 of file yubihsm.c.

1730 {
1731
1732 if (session == NULL || key_id == NULL || label == NULL ||
1733 strlen(label) > YH_OBJ_LABEL_LEN || k == NULL) {
1736 }
1737
1738 uint16_t component_len;
1739 switch (algorithm) {
1740 case YH_ALGO_EC_ED25519:
1741 component_len = 32;
1742 break;
1743 default:
1745 }
1746 return import_asymmetric(session, key_id, label, domains, capabilities,
1747 algorithm, k, component_len);
1748}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_hmac_key()

yh_rc yh_util_import_hmac_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const uint8_t * key,
size_t key_len )

Import an HMAC key into the device

Parameters
sessionAuthenticated session to use
key_idObject ID of the key. 0 if the Object ID should be generated by the device
labelLabel of the key. Maxium length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm of the key to import. Must be one of: YH_ALGO_HMAC_SHA1, YH_ALGO_HMAC_SHA256, YH_ALGO_HMAC_SHA384 or YH_ALGO_HMAC_SHA512
keyThe HMAC key to import
key_lenLength of the HMAC key to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL. See yh_rc for other possible errors

Definition at line 1750 of file yubihsm.c.

1754 {
1755
1756 if (session == NULL || key_id == NULL || label == NULL ||
1757 strlen(label) > YH_OBJ_LABEL_LEN || key == NULL) {
1760 }
1761
1762#pragma pack(push, 1)
1763 union {
1764 struct {
1770 uint8_t key[128];
1771 };
1772 uint8_t buf[1];
1773 } k;
1774 union {
1775 struct {
1777 };
1778 uint8_t buf[1];
1779 } response;
1780#pragma pack(pop)
1781 yh_rc yrc;
1782 size_t response_len = sizeof(response);
1783 yh_cmd response_cmd;
1784 size_t max_len = 64;
1785 int len = sizeof(k) - sizeof(k.key);
1786
1787 k.key_id = htons(*key_id);
1788
1789 memcpy(k.label, label, strlen(label));
1790 memset(k.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
1791
1792 k.domains = htons(domains);
1793
1794 k.algorithm = algorithm;
1795
1796 memcpy(k.capabilities, capabilities, YH_CAPABILITIES_LEN);
1797
1799 max_len = 128;
1800 }
1801
1802 if (key_len > max_len) {
1803 DBG_ERR("Too long key supplied, max %lu bytes allowed",
1804 (unsigned long) max_len);
1805 return YHR_WRONG_LENGTH;
1806 }
1807
1808 memcpy(k.key, key, key_len);
1809 len += key_len;
1810
1811 yrc = yh_send_secure_msg(session, YHC_PUT_HMAC_KEY, k.buf, len, &response_cmd,
1812 response.buf, &response_len);
1813 insecure_memzero(k.buf, len);
1814 if (yrc != YHR_SUCCESS) {
1815 DBG_ERR("Failed to send PUT HMAC KEY command: %s", yh_strerror(yrc));
1816 return yrc;
1817 }
1818
1819 if (response_cmd == YHC_ERROR) {
1820 yh_rc translated = translate_device_error(response.buf[0]);
1821 DBG_ERR("Unable to put key: %s (%x)", yh_strerror(translated),
1822 response.buf[0]);
1823 return translated;
1824 }
1825
1826 *key_id = ntohs(response.key_id);
1827 DBG_INFO("Stored HMAC key 0x%04x", *key_id);
1828
1829 return yrc;
1830}
session operation op sign key_len
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_opaque()

yh_rc yh_util_import_opaque ( yh_session * session,
uint16_t * object_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const uint8_t * in,
size_t in_len )

Import an YH_OPAQUE object into the device

Parameters
sessionAuthenticated session to use
object_idObject ID of the Opaque object. 0 if the Object ID should be generated by the device
labelLabel of the Opaque object. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains the Opaque object will be operating within. See yh_string_to_domains()
capabilitiesCapabilities of the Opaque object. See yh_string_to_capabilities()
algorithmAlgorithm of the Opaque object
inthe Opaque object to import
in_lenLength of the Opaque object to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or in_len is too big. See yh_rc for other possible errors

Definition at line 2666 of file yubihsm.c.

2670 {
2671
2672 if (session == NULL || object_id == NULL || label == NULL ||
2673 strlen(label) > YH_OBJ_LABEL_LEN || in == NULL) {
2676 }
2677
2678 yh_rc yrc;
2679
2680#pragma pack(push, 1)
2681 union {
2682 struct {
2683 uint16_t object_id;
2688 uint8_t bytes[YH_MSG_BUF_SIZE - sizeof(object_id) - sizeof(domains) -
2690 };
2691 uint8_t buf[1];
2692 } data;
2693 uint16_t data_len;
2694 union {
2695 struct {
2696 uint16_t object_id;
2697 };
2698 uint8_t buf[1];
2699 } response;
2700#pragma pack(pop)
2701 size_t response_len = sizeof(response);
2702 yh_cmd response_cmd;
2703
2704 data.object_id = htons(*object_id);
2705
2706 memcpy(data.label, label, strlen(label));
2707 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2708
2709 data.domains = htons(domains);
2710
2711 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2712
2713 data.algorithm = algorithm;
2714
2715 if (in_len > sizeof(data.bytes)) {
2716 DBG_ERR("Data length must be in [0, %lu]\n",
2717 (unsigned long) sizeof(data.bytes));
2719 }
2720
2721 data_len = in_len + sizeof(data) - sizeof(data.bytes);
2722 memcpy(data.bytes, in, in_len);
2723
2724 yrc = yh_send_secure_msg(session, YHC_PUT_OPAQUE, data.buf, data_len,
2725 &response_cmd, response.buf, &response_len);
2726 insecure_memzero(data.buf, data_len);
2727 if (yrc != YHR_SUCCESS) {
2728 DBG_ERR("Failed to send PUT OPAQUE command: %s", yh_strerror(yrc));
2729 return yrc;
2730 }
2731
2732 if (response_cmd == YHC_ERROR) {
2733 yh_rc translated = translate_device_error(response.buf[0]);
2734 DBG_ERR("Unable to store opaque object: %s (%x)", yh_strerror(translated),
2735 response.buf[0]);
2736 return translated;
2737 }
2738
2739 *object_id = ntohs(response.object_id);
2740 DBG_INFO("Stored Opaque Object 0x%04x", *object_id);
2741
2742 return YHR_SUCCESS;
2743}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_otp_aead_key()

yh_rc yh_util_import_otp_aead_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
uint32_t nonce_id,
const uint8_t * in,
size_t in_len )

Import an YH_OTP_AEAD_KEY used for Yubico OTP Decryption

Parameters
sessionAuthenticated session to use
key_idObject ID of the AEAD Key. 0 if the Object ID should be generated by the device
labelLabel of the AEAD Key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains the AEAD Key will be operating within. See yh_string_to_domains()
capabilitiesCapabilities of the AEAD Key. See yh_string_to_capabilities()
nonce_idNonce ID
inAEAD Key to import
in_lenLength of AEAD Key to import. Must be 16, 24 or 32
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if in_len is not one of 16, 24 or 32. See yh_rc for other possible errors

Definition at line 3337 of file yubihsm.c.

3341 {
3342
3343 if (session == NULL || key_id == NULL || label == NULL ||
3344 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL || in == NULL) {
3347 }
3348#pragma pack(push, 1)
3349 union {
3350 struct {
3356 uint32_t nonce_id;
3357 uint8_t key[32];
3358 };
3359 uint8_t buf[1];
3360 } data;
3361 union {
3362 struct {
3364 };
3365 uint8_t buf[1];
3366 } response;
3367#pragma pack(pop)
3368
3369 uint16_t data_len = sizeof(data);
3370 size_t response_len = sizeof(response);
3371 yh_cmd response_cmd;
3372
3373 yh_rc yrc;
3374
3375 if (in_len == 16) {
3376 data.algorithm = YH_ALGO_AES128_YUBICO_OTP;
3377 data_len -= 16;
3378 } else if (in_len == 24) {
3379 data.algorithm = YH_ALGO_AES192_YUBICO_OTP;
3380 data_len -= 8;
3381 } else if (in_len == 32) {
3382 data.algorithm = YH_ALGO_AES256_YUBICO_OTP;
3383 } else {
3384 DBG_ERR("Key length has to be 16, 24 or 32 bytes.");
3386 }
3387
3388 data.key_id = htons(*key_id);
3389
3390 memcpy(data.label, label, strlen(label));
3391 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
3392
3393 data.domains = htons(domains);
3394
3395 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
3396
3397 data.nonce_id = nonce_id;
3398
3399 memcpy(data.key, in, in_len);
3400
3401 yrc = yh_send_secure_msg(session, YHC_PUT_OTP_AEAD_KEY, data.buf, data_len,
3402 &response_cmd, response.buf, &response_len);
3403 insecure_memzero(data.buf, data_len);
3404 if (yrc != YHR_SUCCESS) {
3405 DBG_ERR("Failed to send PUT OTP AEAD KEY command: %s", yh_strerror(yrc));
3406 return yrc;
3407 }
3408
3409 if (response_cmd == YHC_ERROR) {
3410 yh_rc translated = translate_device_error(response.buf[0]);
3411 DBG_ERR("Unable to store OTP AEAD key: %s (%x)", yh_strerror(translated),
3412 response.buf[0]);
3413 return translated;
3414 }
3415
3416 *key_id = ntohs(response.key_id);
3417 DBG_INFO("Imported OTP AEAD key 0x%04x", *key_id);
3418
3419 return YHR_SUCCESS;
3420}
@ YH_ALGO_AES192_YUBICO_OTP
aes192-yubico-otp
Definition yubihsm.h:468
@ YH_ALGO_AES128_YUBICO_OTP
aes128-yubico-otp
Definition yubihsm.h:464
@ YH_ALGO_AES256_YUBICO_OTP
aes256-yubico-otp
Definition yubihsm.h:470
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_rsa_key()

yh_rc yh_util_import_rsa_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const uint8_t * p,
const uint8_t * q )

Import an RSA key into the device

Parameters
sessionAuthenticated session to use
key_idObject ID the key. 0 if Object ID should be generated by the device
labelLabel of the key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains to which the key belongs specified as an unsigned int. See yh_string_to_domains()
capabilitiesCapabilities of the key. See yh_string_to_capabilities()
algorithmAlgorithm of the key to import. Must be one of: YH_ALGO_RSA_2048, YH_ALGO_RSA_3072 or YH_ALGO_RSA_4096
pP component of the RSA key to import
qQ component of the RSA key to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or the algorithm is not one of YH_ALGO_RSA_2048, YH_ALGO_RSA_3072 or YH_ALGO_RSA_4096. See yh_rc for other possible errors

Definition at line 1655 of file yubihsm.c.

1659 {
1660
1661 if (session == NULL || key_id == NULL || label == NULL ||
1662 strlen(label) > YH_OBJ_LABEL_LEN || p == NULL || q == NULL) {
1665 }
1666
1667 uint8_t keybuf[256 * 2];
1668 uint16_t component_len;
1669
1670 if (algorithm == YH_ALGO_RSA_2048) {
1671 component_len = 128;
1672 } else if (algorithm == YH_ALGO_RSA_3072) {
1673 component_len = 192;
1674 } else if (algorithm == YH_ALGO_RSA_4096) {
1675 component_len = 256;
1676 } else {
1678 }
1679 memcpy(keybuf, p, component_len);
1680 memcpy(keybuf + component_len, q, component_len);
1681
1682 yh_rc yrc = import_asymmetric(session, key_id, label, domains, capabilities,
1683 algorithm, keybuf, component_len * 2);
1684 insecure_memzero(keybuf, sizeof(keybuf));
1685
1686 return yrc;
1687}
const mie::Vuint & p
Definition bn.cpp:27
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_template()

yh_rc yh_util_import_template ( yh_session * session,
uint16_t * object_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const uint8_t * in,
size_t in_len )

Import a YH_TEMPLATE object into the device

Parameters
sessionAuthenticated session to use
object_idObject ID of the Template. 0 if the Object ID should be generated by the device
labelLabel of the Template. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains the Template will be operating within. See yh_string_to_domains()
capabilitiesCapabilities of the Template. See yh_string_to_capabilities
algorithmAlgorithm of the Template
inTemplate to import
in_lenLength of the Template to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if in_len is too big. See yh_rc for other possible errors

Definition at line 2835 of file yubihsm.c.

2839 {
2840
2841 if (session == NULL || object_id == NULL || label == NULL ||
2842 strlen(label) > YH_OBJ_LABEL_LEN || in == NULL || in_len == 0) {
2845 }
2846
2847 yh_rc yrc;
2848
2849#pragma pack(push, 1)
2850 union {
2851 struct {
2852 uint16_t object_id;
2857 uint8_t bytes[YH_MSG_BUF_SIZE - sizeof(object_id) - sizeof(domains) -
2859 };
2860 uint8_t buf[1];
2861 } data;
2862 uint16_t data_len;
2863 union {
2864 struct {
2865 uint16_t object_id;
2866 };
2867 uint8_t buf[1];
2868 } response;
2869#pragma pack(pop)
2870
2871 size_t response_len = sizeof(response);
2872 yh_cmd response_cmd;
2873
2874 data.object_id = htons(*object_id);
2875
2876 memcpy(data.label, label, strlen(label));
2877 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2878
2879 data.domains = htons(domains);
2880
2881 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2882
2883 data.algorithm = algorithm;
2884
2885 if (in_len > sizeof(data.bytes)) {
2886 DBG_ERR("Data length must be in [0, %lu]\n",
2887 (unsigned long) sizeof(data.bytes));
2889 }
2890
2891 data_len = in_len + sizeof(data.object_id) + sizeof(data.domains) +
2892 YH_CAPABILITIES_LEN + YH_OBJ_LABEL_LEN + sizeof(data.algorithm);
2893 memcpy(data.bytes, in, in_len);
2894
2895 yrc = yh_send_secure_msg(session, YHC_PUT_TEMPLATE, data.buf, data_len,
2896 &response_cmd, response.buf, &response_len);
2897 if (yrc != YHR_SUCCESS) {
2898 DBG_ERR("Failed to send PUT TEMPLATE command: %s", yh_strerror(yrc));
2899 return yrc;
2900 }
2901
2902 if (response_cmd == YHC_ERROR) {
2903 yh_rc translated = translate_device_error(response.buf[0]);
2904 DBG_ERR("Unable to store template object: %s (%x)", yh_strerror(translated),
2905 response.buf[0]);
2906 return translated;
2907 }
2908
2909 *object_id = ntohs(response.object_id);
2910 DBG_INFO("Stored Opaque Object 0x%04x", *object_id);
2911
2912 return YHR_SUCCESS;
2913}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_wrap_key()

yh_rc yh_util_import_wrap_key ( yh_session * session,
uint16_t * key_id,
const char * label,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const yh_capabilities * delegated_capabilities,
const uint8_t * in,
size_t in_len )

Import a Wrap Key into the device

Parameters
sessionAuthenticated session to use
key_idObject ID the Wrap Key. 0 if the Object ID should be generated by the device
labelLabel of the Wrap Key. Maximum length is YH_OBJ_LABEL_LEN
domainsDomains where the Wrap Key will be operating within. See yh_string_to_domains()
capabilitiesCapabilities of the Wrap Key. See yh_string_to_capabilities()
algorithmAlgorithm of the Wrap Key. Supported algorithms: YH_ALGO_AES128_CCM_WRAP, YH_ALGO_AES192_CCM_WRAP and YH_ALGO_AES256_CCM_WRAP
delegated_capabilitiesDelegated capabilities of the Wrap Key. See yh_string_to_capabilities()
inthe Wrap Key to import
in_lenLength of the Wrap Key to import
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL, in_len is not what expected based on the algorithm and if the algorithms is not one of YH_ALGO_AES128_CCM_WRAP, YH_ALGO_AES192_CCM_WRAP or YH_ALGO_AES256_CCM_WRAP. See yh_rc for other possible errors

Definition at line 2363 of file yubihsm.c.

2368 {
2369
2370 if (session == NULL || key_id == NULL || label == NULL ||
2371 strlen(label) > YH_OBJ_LABEL_LEN || capabilities == NULL ||
2372 delegated_capabilities == NULL || in == NULL) {
2375 }
2376
2377#pragma pack(push, 1)
2378 union {
2379 struct {
2386 uint8_t key[32];
2387 };
2388 uint8_t buf[1];
2389 } data;
2390 uint16_t data_len = sizeof(data);
2391 union {
2392 struct {
2394 };
2395 uint8_t buf[1];
2396 } response;
2397#pragma pack(pop)
2398
2399 size_t response_len = sizeof(response);
2400 yh_cmd response_cmd;
2402
2403 yh_rc yrc;
2404
2405 switch (algorithm) {
2407 key_len = 16;
2408 data_len -= 16;
2409 break;
2411 key_len = 24;
2412 data_len -= 8;
2413 break;
2415 key_len = 32;
2416 break;
2417 default:
2418 DBG_ERR("Bad algorithm specified: %x", algorithm);
2420 }
2421
2422 if (in_len != key_len) {
2423 DBG_ERR("Key length not matching, should be %d", key_len);
2425 }
2426
2427 data.key_id = htons(*key_id);
2428 memcpy(data.label, label, strlen(label));
2429 memset(data.label + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
2430 data.domains = htons(domains);
2431 memcpy(data.capabilities, capabilities, YH_CAPABILITIES_LEN);
2432 data.algorithm = algorithm;
2433 memcpy(data.delegated_capabilities, delegated_capabilities,
2435 memcpy(data.key, in, key_len);
2436
2437 yrc = yh_send_secure_msg(session, YHC_PUT_WRAP_KEY, data.buf, data_len,
2438 &response_cmd, response.buf, &response_len);
2439 insecure_memzero(data.buf, data_len);
2440 if (yrc != YHR_SUCCESS) {
2441 DBG_ERR("Failed to send PUT WRAP KEY command: %s", yh_strerror(yrc));
2442 return yrc;
2443 }
2444
2445 if (response_cmd == YHC_ERROR) {
2446 yh_rc translated = translate_device_error(response.buf[0]);
2447 DBG_ERR("Unable to store wrapping key: %s (%x)", yh_strerror(translated),
2448 response.buf[0]);
2449 return translated;
2450 }
2451
2452 *key_id = ntohs(response.key_id);
2453 DBG_INFO("Imported Wrap key 0x%04x", *key_id);
2454
2455 return YHR_SUCCESS;
2456}
@ YH_ALGO_AES256_CCM_WRAP
aes256-ccm-wrap
Definition yubihsm.h:474
@ YH_ALGO_AES192_CCM_WRAP
aes192-ccm-wrap
Definition yubihsm.h:472
@ YH_ALGO_AES128_CCM_WRAP
aes128-ccm-wrap
Definition yubihsm.h:448
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_import_wrapped()

yh_rc yh_util_import_wrapped ( yh_session * session,
uint16_t wrapping_key_id,
const uint8_t * in,
size_t in_len,
yh_object_type * target_type,
uint16_t * target_id )

Import a wrapped object into the device. The object should have been previously exported by yh_util_export_wrapped()

Parameters
sessionAuthenticated session to use
wrapping_key_idObject ID of the Wrap Key to use to unwrap the object
inWrapped data
in_lenLength of wrapped data
target_typeType of the imported object
target_idObject ID of the imported object
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 2309 of file yubihsm.c.

2311 {
2312
2313 if (session == NULL || in == NULL || target_type == NULL ||
2314 target_id == NULL) {
2317 }
2318
2319 if (in_len > YH_MSG_BUF_SIZE - 2) {
2320 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
2322 }
2323
2324#pragma pack(push, 1)
2325 union {
2326 struct {
2329 };
2330 uint8_t buf[1];
2331 } data;
2332#pragma pack(pop)
2333 uint16_t data_len = 2 + in_len;
2334
2335 uint8_t response[YH_MSG_BUF_SIZE];
2336 size_t response_len = sizeof(response);
2337 yh_cmd response_cmd;
2338 yh_rc yrc;
2339
2340 data.key_id = htons(wrapping_key_id);
2341 memcpy(data.bytes, in, in_len);
2342
2343 yrc = yh_send_secure_msg(session, YHC_IMPORT_WRAPPED, data.buf, data_len,
2344 &response_cmd, response, &response_len);
2345 if (yrc != YHR_SUCCESS) {
2346 DBG_ERR("Failed to send IMPORT WRAPPED command: %s", yh_strerror(yrc));
2347 return yrc;
2348 }
2349
2350 if (response_cmd == YHC_ERROR) {
2351 yh_rc translated = translate_device_error(response[0]);
2352 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated),
2353 response[0]);
2354 return translated;
2355 }
2356
2357 *target_type = response[0];
2358 *target_id = ntohs(*((uint16_t *) (response + 1)));
2359
2360 return YHR_SUCCESS;
2361}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_list_objects()

yh_rc yh_util_list_objects ( yh_session * session,
uint16_t id,
yh_object_type type,
uint16_t domains,
const yh_capabilities * capabilities,
yh_algorithm algorithm,
const char * label,
yh_object_descriptor * objects,
size_t * n_objects )

List objects accessible from the session

Parameters
sessionAuthenticated session to use
idObject ID to filter by (0 to not filter by ID)
typeObject type to filter by (0 to not filter by type). See yh_object_type
domainsDomains to filter by (0 to not filter by domain)
capabilitiesCapabilities to filter by (0 to not filter by capabilities). See yh_capabilities
algorithmAlgorithm to filter by (0 to not filter by algorithm)
labelLabel to filter by
objectsArray of objects returned
n_objectsMax number of objects (will be set to number found on return)
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. YHR_BUFFER_TOO_SMALL if n_objects is smaller than the number of objects found. See yh_rc for other possible errors.
See also
Objects, Domains, Capabilities, Algorithms, Labels

Definition at line 1030 of file yubihsm.c.

1034 {
1035
1036 if (session == NULL || objects == NULL || n_objects == NULL ||
1037 (label != NULL && strlen(label) > YH_OBJ_LABEL_LEN)) {
1040 }
1041
1043 uint8_t *dataptr = data;
1044
1045 uint8_t response[YH_MSG_BUF_SIZE];
1046 size_t response_len = sizeof(response);
1047
1048 yh_rc yrc;
1049 yh_cmd response_cmd;
1050
1051 if (id) {
1052 *dataptr++ = LIST_ID;
1053 *dataptr++ = id >> 8 & 0xff;
1054 *dataptr++ = id & 0xff;
1055 }
1056
1057 if (type) {
1058 *dataptr++ = LIST_TYPE;
1059 *dataptr++ = type;
1060 }
1061
1062 if (domains) {
1063 *dataptr++ = LIST_DOMAINS;
1064 *dataptr++ = domains >> 8 & 0xff;
1065 *dataptr++ = domains & 0xff;
1066 }
1067
1068 if (algorithm) {
1069 *dataptr++ = LIST_ALGORITHM;
1070 *dataptr++ = algorithm;
1071 }
1072
1073 if (label && strlen(label)) {
1074 *dataptr++ = LIST_LABEL;
1075 memcpy(dataptr, label, strlen(label));
1076 memset(dataptr + strlen(label), 0, YH_OBJ_LABEL_LEN - strlen(label));
1077 dataptr += YH_OBJ_LABEL_LEN;
1078 }
1079
1080 bool send_capabilities = false;
1081 for (uint16_t i = 0; i < YH_CAPABILITIES_LEN; i++) {
1082 if (capabilities->capabilities[i]) {
1083 send_capabilities = true;
1084 break;
1085 }
1086 }
1087
1088 if (send_capabilities == true) {
1089 *dataptr++ = LIST_CAPABILITIES;
1090 for (uint16_t i = 0; i < YH_CAPABILITIES_LEN; i++) {
1091 *dataptr++ = capabilities->capabilities[i];
1092 }
1093 }
1094
1095 yrc = yh_send_secure_msg(session, YHC_LIST_OBJECTS, data, dataptr - data,
1096 &response_cmd, response, &response_len);
1097 if (yrc != YHR_SUCCESS) {
1098 DBG_ERR("Failed to send LIST OBJECTS command: %s", yh_strerror(yrc));
1099 return yrc;
1100 }
1101
1102 if (response_cmd == YHC_ERROR) {
1103 yh_rc translated = translate_device_error(response[0]);
1104 DBG_ERR("Unable to list objects: %s (%x)", yh_strerror(translated),
1105 response[0]);
1106 return translated;
1107 }
1108
1109 if ((response_len / 4) > *n_objects) {
1110 DBG_ERR("Objects buffer too small");
1111 return YHR_BUFFER_TOO_SMALL;
1112 }
1113
1114 *n_objects = response_len / 4;
1115 for (uint16_t i = 0; i < response_len; i += 4) {
1116 // NOTE: clear the fields that we didn't set
1117 memset(&objects[i / 4], 0, sizeof(yh_object_descriptor));
1118 objects[i / 4].id = ntohs(*((uint16_t *) (response + i)));
1119 objects[i / 4].type = response[i + 2];
1120 objects[i / 4].sequence = response[i + 3];
1121 }
1122
1123 DBG_INFO("Found %zu objects", *n_objects);
1124
1125 return YHR_SUCCESS;
1126}
uint8_t sequence
Object sequence.
Definition yubihsm.h:554
uint16_t id
Object ID.
Definition yubihsm.h:544
yh_object_type type
Object type.
Definition yubihsm.h:550
#define LIST_LABEL
Definition yubihsm.c:1028
#define LIST_ID
Definition yubihsm.c:1023
#define LIST_DOMAINS
Definition yubihsm.c:1025
#define LIST_ALGORITHM
Definition yubihsm.c:1027
#define LIST_TYPE
Definition yubihsm.c:1024
#define LIST_CAPABILITIES
Definition yubihsm.c:1026
session operation op find n_objects
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_randomize_otp_aead()

yh_rc yh_util_randomize_otp_aead ( yh_session * session,
uint16_t key_id,
uint8_t * out,
size_t * out_len )

Create OTP AEAD from random data

Parameters
sessionAuthenticated session to use
key_idObject ID of the Otp-aead Key to use
outThe created AEAD
out_lenLength of the created AEAD
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 3223 of file yubihsm.c.

3224 {
3225
3226 if (session == NULL || out == NULL || out_len == NULL) {
3229 }
3230#pragma pack(push, 1)
3231 union {
3232 struct {
3234 };
3235 uint8_t buf[1];
3236 } data;
3237#pragma pack(pop)
3238
3239 yh_cmd response_cmd;
3240
3241 data.key_id = htons(key_id);
3242
3243 yh_rc yrc = yh_send_secure_msg(session, YHC_RANDOMIZE_OTP_AEAD, data.buf,
3244 sizeof(data), &response_cmd, out, out_len);
3245 if (yrc != YHR_SUCCESS) {
3246 DBG_ERR("Failed to send RANDOMIZE OTP AEAD command: %s\n",
3247 yh_strerror(yrc));
3248 return yrc;
3249 }
3250
3251 if (response_cmd == YHC_ERROR) {
3252 yh_rc translated = translate_device_error(out[0]);
3253 DBG_ERR("Unable to get OTP AEAD: %s (%x)\n", yh_strerror(translated),
3254 out[0]);
3255 return translated;
3256 }
3257
3258 return YHR_SUCCESS;
3259}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_reset_device()

yh_rc yh_util_reset_device ( yh_session * session)

Factory reset the device. Resets and reboots the device, deletes all Objects and restores the default YH_AUTHENTICATION_KEY.

Parameters
sessionAuthenticated session to use
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. See yh_rc for other possible errors

Definition at line 3796 of file yubihsm.c.

3796 {
3797
3798 if (session == NULL) {
3801 }
3802
3803 yh_rc yrc;
3804
3805 yh_cmd response_cmd;
3806 uint8_t response[1];
3807 size_t response_len = sizeof(response);
3808
3809 yrc = yh_send_secure_msg(session, YHC_RESET_DEVICE, NULL, 0, &response_cmd,
3810 response, &response_len);
3811 if (yrc != YHR_SUCCESS) {
3812 DBG_ERR("Failed to send RESET DEVICE command: %s\n", yh_strerror(yrc));
3813 return yrc;
3814 }
3815
3816 if (response_cmd == YHC_ERROR) {
3817 yh_rc translated = translate_device_error(response[0]);
3818 DBG_ERR("Unable to reset: %s (%x)\n", yh_strerror(translated), response[0]);
3819 return translated;
3820 }
3821
3822 return YHR_SUCCESS;
3823}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_set_log_index()

yh_rc yh_util_set_log_index ( yh_session * session,
uint16_t index )

Set the index of the last extracted log entry.

This function should be called after yh_util_get_log_entries() to inform the device what the last extracted log entry is so new logs can be written. This is used when forced auditing is enabled.

Parameters
sessionAuthenticated session to use
indexindex to set. Should be the same index as the last entry extracted using yh_util_get_log_entries()
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if the session is NULL. See yh_rc for other possible errors

Definition at line 2606 of file yubihsm.c.

2606 {
2607 if (session == NULL) {
2610 }
2611 uint8_t data[2];
2612 yh_cmd response_cmd;
2613 yh_rc yrc;
2614 uint8_t response[YH_MSG_BUF_SIZE];
2615 size_t response_len = sizeof(response);
2616
2617 uint16_t index_h = htons(index);
2618 memcpy(data, &index_h, sizeof(index_h));
2619 yrc = yh_send_secure_msg(session, YHC_SET_LOG_INDEX, data, sizeof(data),
2620 &response_cmd, response, &response_len);
2621 if (yrc != YHR_SUCCESS) {
2622 DBG_ERR("Failed to send SET LOG INDEX command: %s", yh_strerror(yrc));
2623 return yrc;
2624 }
2625
2626 if (response_cmd == YHC_ERROR) {
2627 yh_rc translated = translate_device_error(response[0]);
2628 DBG_ERR("Unable to set log index: %s (%x)", yh_strerror(translated),
2629 response[0]);
2630 return translated;
2631 }
2632
2633 return YHR_SUCCESS;
2634}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_set_option()

yh_rc yh_util_set_option ( yh_session * session,
yh_option option,
size_t len,
uint8_t * val )

Set a device-global option

Parameters
sessionAuthenticated session to use
optionOption to set. See yh_option
lenLength of option value
valOption value
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if session or val are NULL or if len is too long. See yh_rc for other possible errors

Definition at line 3537 of file yubihsm.c.

3538 {
3539
3540 if (session == NULL || val == NULL) {
3543 }
3544
3545 if (len > YH_MSG_BUF_SIZE - 3) {
3546 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 3);
3548 }
3549
3550#pragma pack(push, 1)
3551 union {
3552 struct {
3554 uint16_t len;
3555 uint8_t bytes[1];
3556 };
3558 } data;
3559#pragma pack(pop)
3561 size_t outlen = sizeof(out);
3562 yh_cmd response_cmd;
3563
3564 data.option = option;
3565 data.len = htons(len);
3566 memcpy(data.bytes, val, len);
3567
3568 yh_rc yrc = yh_send_secure_msg(session, YHC_SET_OPTION, data.buf, len + 3,
3569 &response_cmd, out, &outlen);
3570 if (yrc != YHR_SUCCESS) {
3571 DBG_ERR("Failed to send SET OPTION command: %s\n", yh_strerror(yrc));
3572 return yrc;
3573 }
3574
3575 if (response_cmd == YHC_ERROR) {
3576 yh_rc translated = translate_device_error(out[0]);
3577 DBG_ERR("Unable to put option: %s (%x)\n", yh_strerror(translated), out[0]);
3578 return translated;
3579 }
3580
3581 return YHR_SUCCESS;
3582}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_attestation_certificate()

yh_rc yh_util_sign_attestation_certificate ( yh_session * session,
uint16_t key_id,
uint16_t attest_id,
uint8_t * out,
size_t * out_len )

Get attestation of an Asymmetric Key in the form of an X.509 certificate

Parameters
sessionAuthenticated session to use
key_idObject ID of the Asymmetric Key to attest
attest_idObject ID for the key used to sign the attestation certificate
outThe attestation certificate
out_lenLength of the attestation certificate
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL. See yh_rc for other possible errors

Definition at line 3495 of file yubihsm.c.

3497 {
3498
3499 if (session == NULL || out == NULL || out_len == NULL) {
3502 }
3503#pragma pack(push, 1)
3504 union {
3505 struct {
3507 uint16_t attest_id;
3508 };
3509 uint8_t buf[1];
3510 } data;
3511#pragma pack(pop)
3512
3513 yh_cmd response_cmd;
3514
3515 data.key_id = htons(key_id);
3516 data.attest_id = htons(attest_id);
3517
3518 yh_rc yrc =
3519 yh_send_secure_msg(session, YHC_SIGN_ATTESTATION_CERTIFICATE, data.buf,
3520 sizeof(data), &response_cmd, out, out_len);
3521 if (yrc != YHR_SUCCESS) {
3522 DBG_ERR("Failed to send SIGN ATTESTATION CERTIFICATE command: %s\n",
3523 yh_strerror(yrc));
3524 return yrc;
3525 }
3526
3527 if (response_cmd == YHC_ERROR) {
3528 yh_rc translated = translate_device_error(out[0]);
3529 DBG_ERR("Unable to get attestation: %s (%x)\n", yh_strerror(translated),
3530 out[0]);
3531 return translated;
3532 }
3533
3534 return YHR_SUCCESS;
3535}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_ecdsa()

yh_rc yh_util_sign_ecdsa ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Sign data using ECDSA

in is a raw hashed message, a truncated hash to the curve length or a padded hash to the curve length

Parameters
sessionAuthenticated session to use
key_idObject ID of the signing key
inData to sign
in_lenLength of data to sign
outSigned data
out_lenLength of signed data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is not 20, 28, 34, 48, 64 or 66. See yh_rc for other possible errors

Definition at line 1411 of file yubihsm.c.

1413 {
1414
1415 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1418 }
1419
1420 switch (in_len) {
1421 case 20:
1422 case 28: // p224..
1423 case 32:
1424 case 48:
1425 case 64:
1426 case 66: // p521 needs 66 bytes input
1427 break;
1428
1429 default:
1430 DBG_ERR("Data length must be 20, 28, 32, 48, 64 or 66");
1432 }
1433
1434 yh_rc yrc;
1435
1436#pragma pack(push, 1)
1437 union {
1438 struct {
1441 };
1442 uint8_t buf[1];
1443 } data;
1444#pragma pack(pop)
1445 uint16_t data_len = in_len;
1446
1447 yh_cmd response_cmd;
1448
1449 data.key_id = htons(key_id);
1450
1451 memcpy(data.bytes, in, in_len);
1452
1453 yrc = yh_send_secure_msg(session, YHC_SIGN_ECDSA, data.buf, data_len + 2,
1454 &response_cmd, out, out_len);
1455 if (yrc != YHR_SUCCESS) {
1456 DBG_ERR("Failed to send SIGN ECDSA command: %s", yh_strerror(yrc));
1457 return yrc;
1458 }
1459
1460 if (response_cmd == YHC_ERROR) {
1461 yh_rc translated = translate_device_error(out[0]);
1462 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1463 out[0]);
1464 return translated;
1465 }
1466
1467 return YHR_SUCCESS;
1468}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_eddsa()

yh_rc yh_util_sign_eddsa ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Sign data using EdDSA

Parameters
sessionAuthenticated session to use
key_idObject ID of the signing key
inData to sign
in_lenLength of data to sign
outSigned data
out_lenLength of signed data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is bigger than YH_MSG_BUF_SIZE-2. See yh_rc for other possible errors

Definition at line 1470 of file yubihsm.c.

1472 {
1473
1474 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1477 }
1478
1479 if (in_len > YH_MSG_BUF_SIZE - 2) {
1480 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
1482 }
1483
1484 yh_rc yrc;
1485
1486#pragma pack(push, 1)
1487 union {
1488 struct {
1491 };
1492 uint8_t buf[1];
1493 } data;
1494#pragma pack(pop)
1495 uint16_t data_len = in_len;
1496
1497 yh_cmd response_cmd;
1498
1499 data.key_id = htons(key_id);
1500
1501 memcpy(data.bytes, in, in_len);
1502
1503 yrc = yh_send_secure_msg(session, YHC_SIGN_EDDSA, data.buf, data_len + 2,
1504 &response_cmd, out, out_len);
1505 if (yrc != YHR_SUCCESS) {
1506 DBG_ERR("Failed to send SIGN EDDSA command: %s", yh_strerror(yrc));
1507 return yrc;
1508 }
1509
1510 if (response_cmd == YHC_ERROR) {
1511 yh_rc translated = translate_device_error(out[0]);
1512 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1513 out[0]);
1514 return translated;
1515 }
1516
1517 return YHR_SUCCESS;
1518}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_hmac()

yh_rc yh_util_sign_hmac ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Sign data using HMAC

Parameters
sessionAuthenticated session to use
key_idObject ID of the signing key
inData to HMAC
in_lenLength of data to hmac
outHMAC
out_lenLength of HMAC
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is bigger than YH_MSG_BUF_SIZE-2. See yh_rc for other possible errors

Definition at line 1520 of file yubihsm.c.

1521 {
1522
1523 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1526 }
1527
1528 if (in_len > YH_MSG_BUF_SIZE - 2) {
1529 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
1531 }
1532
1534 uint16_t data_len = 2;
1535
1536 yh_cmd response_cmd;
1537
1538 data[0] = htons(key_id) & 0xff;
1539 data[1] = htons(key_id) >> 8;
1540
1541 memcpy(data + 2, in, in_len);
1542 data_len += in_len;
1543
1544 yh_rc yrc = yh_send_secure_msg(session, YHC_SIGN_HMAC, data, data_len,
1545 &response_cmd, out, out_len);
1546 if (yrc != YHR_SUCCESS) {
1547 DBG_ERR("Failed to send SIGN HMAC command: %s", yh_strerror(yrc));
1548 return yrc;
1549 }
1550
1551 if (response_cmd == YHC_ERROR) {
1552 yh_rc translated = translate_device_error(out[0]);
1553 DBG_ERR("Unable to get data: %s (%x)", yh_strerror(translated), out[0]);
1554 return translated;
1555 }
1556
1557 return YHR_SUCCESS;
1558}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_pkcs1v1_5()

yh_rc yh_util_sign_pkcs1v1_5 ( yh_session * session,
uint16_t key_id,
bool hashed,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Sign data using RSA-PKCS#1v1.5

in is either a raw hashed message (sha1, sha256, sha384 or sha512) or that with correct digestinfo pre-pended

Parameters
sessionAuthenticated session to use
key_idObject ID of the signing key
hashedtrue if data is only hashed
indata to sign
in_lenlength of data to sign
outsigned data
out_lenlength of signed data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is not 20, 34, 48 or 64. See yh_rc for other possible errors

Definition at line 1287 of file yubihsm.c.

1289 {
1290
1291 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1294 }
1295
1296 if (hashed)
1297 switch (in_len) {
1298 case 20:
1299 case 32:
1300 case 48:
1301 case 64:
1302 break;
1303
1304 default:
1305 DBG_ERR("Data length must be 20, 32, 48 or 64");
1307 }
1308
1309 yh_rc yrc;
1310
1311#pragma pack(push, 1)
1312 union {
1313 struct {
1316 };
1317 uint8_t buf[1];
1318 } data;
1319#pragma pack(pop)
1320 uint16_t data_len;
1321
1322 yh_cmd response_cmd;
1323
1324 data.key_id = htons(key_id);
1325
1326 memcpy(data.bytes, in, in_len);
1327 data_len = in_len;
1328
1329 yrc = yh_send_secure_msg(session, YHC_SIGN_PKCS1, data.buf, data_len + 2,
1330 &response_cmd, out, out_len);
1331 if (yrc != YHR_SUCCESS) {
1332 DBG_ERR("Failed to send SIGN PKCS1 command: %s", yh_strerror(yrc));
1333 return yrc;
1334 }
1335
1336 if (response_cmd == YHC_ERROR) {
1337 yh_rc translated = translate_device_error(out[0]);
1338 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1339 out[0]);
1340 return translated;
1341 }
1342
1343 return YHR_SUCCESS;
1344}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_pss()

yh_rc yh_util_sign_pss ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len,
size_t salt_len,
yh_algorithm mgf1Algo )

Sign data using RSA-PSS

in is a raw hashed message (sha1, sha256, sha384 or sha512)

Parameters
sessionAuthenticated session to use
key_idObject ID of the signing key
inData to sign
in_lenLength of data to sign
outSigned data
out_lenLength of signed data
salt_lenLength of salt
mgf1AlgoAlgorithm for mgf1 (mask generation function for PSS)
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if in_len is not 20, 34, 48 or 64. See yh_rc for other possible errors
See also
PSS specifications

Definition at line 1346 of file yubihsm.c.

1348 {
1349
1350 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
1353 }
1354
1355 switch (in_len) {
1356 case 20:
1357 case 32:
1358 case 48:
1359 case 64:
1360 break;
1361
1362 default:
1363 DBG_ERR("Data length must be 20, 32, 48 or 64");
1365 }
1366
1367 yh_rc yrc;
1368
1369#pragma pack(push, 1)
1370 union {
1371 struct {
1373 uint8_t mgf1Algo;
1374 uint16_t salt_len;
1376 };
1377 uint8_t buf[1];
1378 } data;
1379#pragma pack(pop)
1380 uint16_t data_len = in_len;
1381
1382 yh_cmd response_cmd;
1383
1384 data.key_id = htons(key_id);
1385
1386 data.mgf1Algo = mgf1Algo;
1387
1388 // NOTE(adma): 'in' is already a hash of the data, which type is inferred from
1389 // the length
1390 data.salt_len = htons(salt_len);
1391
1392 memcpy(data.bytes, in, in_len);
1393
1394 yrc = yh_send_secure_msg(session, YHC_SIGN_PSS, data.buf, data_len + 5,
1395 &response_cmd, out, out_len);
1396 if (yrc != YHR_SUCCESS) {
1397 DBG_ERR("Failed to send SIGN PSS command: %s", yh_strerror(yrc));
1398 return yrc;
1399 }
1400
1401 if (response_cmd == YHC_ERROR) {
1402 yh_rc translated = translate_device_error(out[0]);
1403 DBG_ERR("Unable to get signature: %s (%x)", yh_strerror(translated),
1404 out[0]);
1405 return translated;
1406 }
1407
1408 return YHR_SUCCESS;
1409}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_sign_ssh_certificate()

yh_rc yh_util_sign_ssh_certificate ( yh_session * session,
uint16_t key_id,
uint16_t template_id,
yh_algorithm sig_algo,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Sign an SSH Certificate request. The function produces a signature that can then be used to produce the SSH Certificate

Parameters
sessionAuthenticated session to use
key_idObject ID of the key used to sign the request
template_idObject ID of the template to use as a certificate template
sig_algoSignature algorithm to use to sign the certificate request
inCertificate request
in_lenLength of the certificate request
outSignature
out_lenLength of the signature
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or in_len is too big. See yh_rc for other possible errors

Definition at line 2745 of file yubihsm.c.

2748 {
2749 if (session == NULL || in == NULL || out == NULL || out_len == NULL ||
2750 in_len == 0) {
2753 }
2754
2755 yh_rc yrc;
2756
2757#pragma pack(push, 1)
2758 union {
2759 struct {
2761 uint16_t template_id;
2762 uint8_t algo;
2763 uint8_t bytes[YH_MSG_BUF_SIZE - sizeof(key_id) - sizeof(template_id) - 2];
2764 };
2765 uint8_t buf[1];
2766 } data;
2767 uint16_t data_len;
2768#pragma pack(pop)
2769
2770 yh_cmd response_cmd;
2771
2772 data.key_id = htons(key_id);
2773
2774 data.template_id = htons(template_id);
2775
2776 data.algo = sig_algo;
2777
2778 if (in_len > sizeof(data.bytes)) {
2779 DBG_ERR("Data length must be in [0, %lu]\n",
2780 (unsigned long) sizeof(data.bytes));
2782 }
2783
2784 data_len = in_len + 5;
2785 memcpy(data.bytes, in, in_len);
2786
2787 yrc = yh_send_secure_msg(session, YHC_SIGN_SSH_CERTIFICATE, data.buf,
2788 data_len, &response_cmd, out, out_len);
2789 if (yrc != YHR_SUCCESS) {
2790 DBG_ERR("Failed to send SIGN SSH CERTIFICATE command: %s",
2791 yh_strerror(yrc));
2792 return yrc;
2793 }
2794
2795 if (response_cmd == YHC_ERROR) {
2796 yh_rc translated = translate_device_error(out[0]);
2797 DBG_ERR("Unable to get certificate: %s (%x)", yh_strerror(translated),
2798 out[0]);
2799 return translated;
2800 }
2801
2802 return YHR_SUCCESS;
2803}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_unwrap_data()

yh_rc yh_util_unwrap_data ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Decrypt (unwrap) data using a YH_WRAP_KEY.

Parameters
sessionAuthenticated session to use
key_idObject ID of the Wrap Key to use
inWrapped data
in_lenLength of wrapped data
outUnwrapped data
out_lenLength of unwrapped data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if in_len is too big. See yh_rc for other possible errors

Definition at line 3716 of file yubihsm.c.

3718 {
3719
3720 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
3723 }
3724
3725 if (in_len > YH_MSG_BUF_SIZE - 2) {
3726 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
3728 }
3729
3730 yh_rc yrc;
3731
3732#pragma pack(push, 1)
3733 union {
3734 struct {
3737 };
3738 uint8_t buf[1];
3739 } data;
3740#pragma pack(pop)
3741 uint16_t data_len = in_len + 2;
3742
3743 yh_cmd response_cmd;
3744
3745 data.key_id = htons(key_id);
3746 memcpy(data.bytes, in, in_len);
3747
3748 yrc = yh_send_secure_msg(session, YHC_UNWRAP_DATA, data.buf, data_len,
3749 &response_cmd, out, out_len);
3750 insecure_memzero(data.buf, data_len);
3751 if (yrc != YHR_SUCCESS) {
3752 DBG_ERR("Failed to send UNWRAP DATA command: %s", yh_strerror(yrc));
3753 return yrc;
3754 }
3755
3756 if (response_cmd == YHC_ERROR) {
3757 yh_rc translated = translate_device_error(out[0]);
3758 DBG_ERR("Unable to get unwrapped data: %s (%x)", yh_strerror(translated),
3759 out[0]);
3760 return translated;
3761 }
3762
3763 return YHR_SUCCESS;
3764}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_verify_hmac()

yh_rc yh_util_verify_hmac ( yh_session * session,
uint16_t key_id,
const uint8_t * signature,
size_t signature_len,
const uint8_t * data,
size_t data_len,
bool * verified )

Verify a generated HMAC

Parameters
sessionAuthenticated session to use
key_idObject ID of the HMAC key
signatureHMAC signature (20, 32, 48 or 64 bytes)
signature_lenlength of HMAC signature
datadata to verify
data_lenlength of data to verify
verifiedtrue if verification succeeded
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS input parameters are NULL or if signature_len + data_len is too long. See yh_rc for other possible errors

Definition at line 1939 of file yubihsm.c.

1942 {
1943
1944 if (session == NULL || signature == NULL || data == NULL ||
1945 verified == NULL) {
1948 }
1949
1950 if (data_len + signature_len > YH_MSG_BUF_SIZE - 2) {
1951 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
1953 }
1954
1955 yh_rc yrc;
1956
1957 uint8_t cmd_data[YH_MSG_BUF_SIZE];
1958 int cmd_data_len;
1959
1960 uint8_t response[3];
1961 size_t response_len = sizeof(response);
1962 yh_cmd response_cmd;
1963
1964 key_id = htons(key_id);
1965
1966 memcpy(cmd_data, (uint8_t *) &key_id, 2);
1967 cmd_data_len = 2;
1968 memcpy(cmd_data + cmd_data_len, signature, signature_len);
1969 cmd_data_len += signature_len;
1970 memcpy(cmd_data + cmd_data_len, data, data_len);
1971 cmd_data_len += data_len;
1972
1973 yrc = yh_send_secure_msg(session, YHC_VERIFY_HMAC, cmd_data, cmd_data_len,
1974 &response_cmd, response, &response_len);
1975 if (yrc != YHR_SUCCESS) {
1976 DBG_ERR("Failed to send HMAC VERIFY command: %s", yh_strerror(yrc));
1977 return yrc;
1978 }
1979
1980 if (response_cmd == YHC_ERROR) {
1981 yh_rc translated = translate_device_error(response[0]);
1982 DBG_ERR("Unable to verify data: %s (%x)", yh_strerror(translated),
1983 response[0]);
1984 return translated;
1985 }
1986
1987 *verified = response[0];
1988
1989 return YHR_SUCCESS;
1990}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_util_wrap_data()

yh_rc yh_util_wrap_data ( yh_session * session,
uint16_t key_id,
const uint8_t * in,
size_t in_len,
uint8_t * out,
size_t * out_len )

Encrypt (wrap) data using a YH_WRAP_KEY.

Parameters
sessionAuthenticated session to use
key_idObject ID of the Wrap Key to use
inData to wrap
in_lenLength of data to wrap
outWrapped data
out_lenLength of the wrapped data
Returns
YHR_SUCCESS if successful. YHR_INVALID_PARAMETERS if input parameters are NULL or if in_len is too big. See yh_rc for other possible errors

Definition at line 3667 of file yubihsm.c.

3668 {
3669
3670 if (session == NULL || in == NULL || out == NULL || out_len == NULL) {
3673 }
3674
3675 if (in_len > YH_MSG_BUF_SIZE - 2) {
3676 DBG_ERR("Too much data, must be < %d", YH_MSG_BUF_SIZE - 2);
3678 }
3679
3680 yh_rc yrc;
3681
3682#pragma pack(push, 1)
3683 union {
3684 struct {
3687 };
3688 uint8_t buf[1];
3689 } data;
3690#pragma pack(pop)
3691 uint16_t data_len = in_len + 2;
3692
3693 yh_cmd response_cmd;
3694
3695 data.key_id = htons(key_id);
3696 memcpy(data.bytes, in, in_len);
3697
3698 yrc = yh_send_secure_msg(session, YHC_WRAP_DATA, data.buf, data_len,
3699 &response_cmd, out, out_len);
3700 insecure_memzero(data.buf, data_len);
3701 if (yrc != YHR_SUCCESS) {
3702 DBG_ERR("Failed to send WRAP DATA command: %s", yh_strerror(yrc));
3703 return yrc;
3704 }
3705
3706 if (response_cmd == YHC_ERROR) {
3707 yh_rc translated = translate_device_error(out[0]);
3708 DBG_ERR("Unable to get wrapped data: %s (%x)", yh_strerror(translated),
3709 out[0]);
3710 return translated;
3711 }
3712
3713 return YHR_SUCCESS;
3714}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ yh_verify_logs()

bool yh_verify_logs ( yh_log_entry * logs,
size_t n_items,
yh_log_entry * last_previous_log )

Verify an array of log entries

Parameters
logsArray of log entries
n_itemsnumber of log entries
last_previous_logOptional pointer to the entry before the first entry in logs
Returns
True if verification succeeds. False otherwise
See also
Logs

Definition at line 4480 of file yubihsm.c.

4481 {
4482 if (logs == NULL || n_items == 0) {
4483 return false;
4484 }
4485
4486 hash_ctx hashctx = NULL;
4487 uint8_t previous_hash[32];
4488 size_t previous_hash_len = 32;
4489 int start;
4490 bool ret = false;
4491
4492 if (!hash_create(&hashctx, _SHA256)) {
4493 return false;
4494 }
4495
4496 if (last_previous_log != NULL) {
4497 memcpy(previous_hash, last_previous_log->digest, YH_LOG_DIGEST_SIZE);
4498 start = 0;
4499 } else {
4500 memcpy(previous_hash, logs[0].digest, YH_LOG_DIGEST_SIZE);
4501 start = 1;
4502 }
4503
4504 for (uint16_t i = start; i < n_items; i++) {
4505 yh_log_entry inverted;
4506 inverted.number = htons(logs[i].number);
4507 inverted.command = logs[i].command;
4508 inverted.length = htons(logs[i].length);
4509 inverted.session_key = htons(logs[i].session_key);
4510 inverted.target_key = htons(logs[i].target_key);
4511 inverted.second_key = htons(logs[i].second_key);
4512 inverted.result = logs[i].result;
4513 inverted.systick = htonl(logs[i].systick);
4514
4515 hash_init(hashctx);
4516 hash_update(hashctx, (const uint8_t *) &inverted,
4518 hash_update(hashctx, previous_hash, YH_LOG_DIGEST_SIZE);
4519 hash_final(hashctx, previous_hash, &previous_hash_len);
4520
4521 if (memcmp(logs[i].digest, previous_hash, YH_LOG_DIGEST_SIZE) != 0) {
4522 goto out;
4523 }
4524 }
4525
4526 ret = true;
4527
4528out:
4529 hash_destroy(hashctx);
4530 hashctx = NULL;
4531
4532 return ret;
4533}
bool hash_update(_hash_ctx *ctx, const uint8_t *in, size_t cb_in)
Definition hash.c:319
bool hash_create(_hash_ctx **ctx, hash_t hash)
Definition hash.c:189
bool hash_init(_hash_ctx *ctx)
Definition hash.c:294
bool hash_destroy(_hash_ctx *ctx)
Definition hash.c:387
bool hash_final(_hash_ctx *ctx, uint8_t *out, size_t *pcb_out)
Definition hash.c:351
uint8_t digest[YH_LOG_DIGEST_SIZE]
Truncated sha256 digest of this last digest + this entry.
Definition yubihsm.h:534
uint16_t second_key
ID of second Object used.
Definition yubihsm.h:528
uint8_t result
Command result.
Definition yubihsm.h:530
uint32_t systick
Systick at time of execution.
Definition yubihsm.h:532
uint16_t session_key
ID of Authentication Key used.
Definition yubihsm.h:524
uint16_t target_key
ID of first Object used.
Definition yubihsm.h:526
uint16_t length
Length of in-data.
Definition yubihsm.h:522
uint8_t command
What command was executed.
Definition yubihsm.h:520
uint16_t number
Monotonically increasing index.
Definition yubihsm.h:518
@ _SHA256
Definition hash.h:36
CK_RV ret
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ YH_INTERNAL

FILE* _yh_output YH_INTERNAL = 0

Definition at line 57 of file yubihsm.c.