Skip to content

Commit

Permalink
Check max message size against firmware version (#420)
Browse files Browse the repository at this point in the history
Check max message size against firmware version
  • Loading branch information
aveenismail authored Sep 2, 2024
1 parent dd10c48 commit d1f325f
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 86 deletions.
1 change: 1 addition & 0 deletions lib/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ struct yh_connector {
char address[32];
uint32_t port;
uint32_t pid;
yh_device_info device_info;
};

#ifndef __WIN32
Expand Down
18 changes: 9 additions & 9 deletions lib/tests/test_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,21 @@ static void test_status(void) {
yh_connector c;
} tests[] = {
{"status=OK\nversion=1.2.3\n",
{NULL, NULL, NULL, {0}, {0}, true, 1, 2, 3, "", 0, 0}},
{"", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0}},
{"foobar", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0}},
{"\n\n\n\n\n\n", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0}},
{NULL, NULL, NULL, {0}, {0}, true, 1, 2, 3, "", 0, 0, {0}}},
{"", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}},
{"foobar", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}},
{"\n\n\n\n\n\n", {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}},
{"status=NO_DEVICE\nserial=*\nversion=1.0.2\npid=412\naddress=\nport=12345",
{NULL, NULL, NULL, {0}, {0}, false, 1, 0, 2, "", 12345, 412}},
{"version=1.2", {NULL, NULL, NULL, {0}, {0}, false, 1, 2, 0, "", 0, 0}},
{NULL, NULL, NULL, {0}, {0}, false, 1, 0, 2, "", 12345, 412, {0}}},
{"version=1.2", {NULL, NULL, NULL, {0}, {0}, false, 1, 2, 0, "", 0, 0, {0}}},
{"version=foobar",
{NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0}},
{NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}}},
{"version=2..\nstatus=OK",
{NULL, NULL, NULL, {0}, {0}, true, 2, 0, 0, "", 0, 0}},
{NULL, NULL, NULL, {0}, {0}, true, 2, 0, 0, "", 0, 0, {0}}},
};

for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
yh_connector c = {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0};
yh_connector c = {NULL, NULL, NULL, {0}, {0}, false, 0, 0, 0, "", 0, 0, {0}};
char *data = strdup(tests[i].data);

parse_status_data(data, &c);
Expand Down
30 changes: 27 additions & 3 deletions lib/yubihsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,17 @@ static yh_rc send_encrypted_msg(Scp_ctx *session, yh_cmd cmd,
return YHR_INVALID_PARAMETERS;
}


int max_message_size = SCP_MSG_BUF_SIZE;
if (session->parent->device_info.major < 2 ||
(session->parent->device_info.major == 2 &&
session->parent->device_info.minor < 4)) {
max_message_size = 2048;
}

// Outer command { cmd | cmd_len | sid | encrypted payload | mac }
if (3 + 1 + len + SCP_MAC_LEN > SCP_MSG_BUF_SIZE) {
DBG_ERR("%s (%u > %u)", yh_strerror(YHR_BUFFER_TOO_SMALL), 3 + 1 + len + SCP_MAC_LEN, SCP_MSG_BUF_SIZE);
if (3 + 1 + len + SCP_MAC_LEN > max_message_size) {
DBG_ERR("%s (%u > %u)", yh_strerror(YHR_BUFFER_TOO_SMALL), 3 + 1 + len + SCP_MAC_LEN, max_message_size);
return YHR_BUFFER_TOO_SMALL;
}

Expand Down Expand Up @@ -1390,6 +1398,17 @@ yh_rc yh_util_get_partnumber(yh_connector *connector, char *part_number,
return YHR_SUCCESS;
}

yh_rc yh_util_get_device_info_ex(yh_connector *connector,
yh_device_info *device_info) {
device_info->n_algorithms = YH_MAX_ALGORITHM_COUNT;
return yh_util_get_device_info(connector, &device_info->major,
&device_info->minor, &device_info->patch,
&device_info->serial, &device_info->log_total,
&device_info->log_used,
device_info->algorithms,
&device_info->n_algorithms);
}

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,
Expand Down Expand Up @@ -4810,12 +4829,17 @@ yh_rc yh_connect(yh_connector *connector, int timeout) {
}

yh_rc rc = connector->bf->backend_connect(connector, timeout);
if (rc != YHR_SUCCESS) {
DBG_ERR("Failed when connecting: %s", yh_strerror(rc));
return rc;
}

rc = yh_util_get_device_info_ex(connector, &connector->device_info);
if (rc != YHR_SUCCESS) {
DBG_ERR("Failed when connecting: %s", yh_strerror(rc));
}

return rc;
return YHR_SUCCESS;
}

yh_rc yh_disconnect(yh_connector *connector) {
Expand Down
39 changes: 39 additions & 0 deletions lib/yubihsm.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,28 @@ typedef enum {
YH_CONNECTOR_NOPROXY = 5,
} yh_connector_option;

/**
* Device info struct
*/
typedef struct {
/// Firmware version major
uint8_t major;
/// Firmware version minor
uint8_t minor;
/// Firmware version patch
uint8_t patch;
/// Device serial number
uint32_t serial;
/// Total available logs
uint8_t log_total;
/// Total used logs
uint8_t log_used;
/// List of algorithms supported by the device
yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT];
/// Number of algorithms supported by the device
size_t n_algorithms;
} yh_device_info;

#pragma pack(push, 1)
/**
* Logging struct as returned by device
Expand Down Expand Up @@ -1221,6 +1243,23 @@ yh_rc yh_authenticate_session(yh_session *session);

// Utility and convenience functions below

/**
* Get device info in a struct
*
* @param connector Connector to the device
* @param device_info Device info
*
* @return #YHR_SUCCESS if successful.
* #YHR_INVALID_PARAMETERS if the connector or device_info 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 <a
*href="https://developers.yubico.com/YubiHSM2/Concepts/Algorithms.html">Algorithms</a>
**/
yh_rc yh_util_get_device_info_ex(yh_connector *connector,
yh_device_info *device_info);

/**
* Get device version, device serial number, supported algorithms and available
*log entries.
Expand Down
85 changes: 46 additions & 39 deletions pkcs11/util_pkcs11.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,22 +202,12 @@ CK_RV get_mechanism_list(yubihsm_pkcs11_slot *slot,
CK_MECHANISM_TYPE_PTR pMechanismList,
CK_ULONG_PTR count) {

if (slot->n_algorithms == 0) {
slot->n_algorithms = sizeof(slot->algorithms) / sizeof(slot->algorithms[0]);
yh_rc yrc =
yh_util_get_device_info(slot->connector, NULL, NULL, NULL, NULL, NULL,
NULL, slot->algorithms, &slot->n_algorithms);
if (yrc != YHR_SUCCESS) {
return yrc_to_rv(yrc);
}
}

// NOTE: this is a bit hardcoded, but much more than what we might add below.
CK_MECHANISM_TYPE buffer[128] = {0};
CK_ULONG items = 0;

for (size_t i = 0; i < slot->n_algorithms; i++) {
switch (slot->algorithms[i]) {
for (size_t i = 0; i < slot->connector->device_info.n_algorithms; i++) {
switch (slot->connector->device_info.algorithms[i]) {
case YH_ALGO_RSA_PKCS1_SHA1:
add_mech(buffer, &items, CKM_RSA_PKCS);
add_mech(buffer, &items, CKM_SHA1_RSA_PKCS);
Expand Down Expand Up @@ -504,17 +494,6 @@ static void find_minmax_aes_key_length_in_bytes(yh_algorithm *algorithms,

CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
CK_MECHANISM_INFO_PTR pInfo) {

if (slot->n_algorithms == 0) {
slot->n_algorithms = sizeof(slot->algorithms) / sizeof(slot->algorithms[0]);
yh_rc yrc =
yh_util_get_device_info(slot->connector, NULL, NULL, NULL, NULL, NULL,
NULL, slot->algorithms, &slot->n_algorithms);
if (yrc != YHR_SUCCESS) {
return yrc_to_rv(yrc);
}
}

pInfo->flags = 0;
switch (type) {
case CKM_RSA_PKCS:
Expand All @@ -524,7 +503,7 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
case CKM_SHA256_RSA_PKCS:
case CKM_SHA384_RSA_PKCS:
case CKM_SHA512_RSA_PKCS:
find_minmax_rsa_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_rsa_key_length_in_bits(slot->connector->device_info.algorithms, slot->connector->device_info.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags |= CKF_HW | CKF_SIGN | CKF_VERIFY;
Expand All @@ -535,36 +514,50 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
case CKM_SHA256_RSA_PKCS_PSS:
case CKM_SHA384_RSA_PKCS_PSS:
case CKM_SHA512_RSA_PKCS_PSS:
find_minmax_rsa_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_rsa_key_length_in_bits(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY;
break;

case CKM_RSA_PKCS_OAEP:
find_minmax_rsa_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_rsa_key_length_in_bits(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_DECRYPT | CKF_ENCRYPT;
break;

case CKM_YUBICO_RSA_WRAP:
case CKM_RSA_AES_KEY_WRAP:
find_minmax_rsa_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_rsa_key_length_in_bits(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_WRAP | CKF_UNWRAP;
break;

case CKM_RSA_PKCS_KEY_PAIR_GEN:
find_minmax_rsa_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_rsa_key_length_in_bits(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR;
break;

case CKM_EC_KEY_PAIR_GEN:
find_minmax_ec_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_ec_key_length_in_bits(slot->connector->device_info.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_GENERATE_KEY_PAIR | CKF_EC_F_P |
Expand Down Expand Up @@ -616,15 +609,19 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
case CKM_ECDSA_SHA512:
// should all ecdsa mechanisms have all keylengths? or should they be
// bounded to length of hash?
find_minmax_ec_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_ec_key_length_in_bits(slot->connector->device_info.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY | CKF_EC_F_P |
CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS;
break;

case CKM_ECDH1_DERIVE:
find_minmax_ec_key_length_in_bits(slot->algorithms, slot->n_algorithms,
find_minmax_ec_key_length_in_bits(slot->connector->device_info.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_DERIVE | CKF_EC_F_P | CKF_EC_NAMEDCURVE |
Expand Down Expand Up @@ -655,12 +652,6 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
pInfo->flags = CKF_DIGEST;
break;

case CKM_AES_KEY_WRAP_KWP:
pInfo->ulMaxKeySize = 256;
pInfo->ulMinKeySize = 128;
pInfo->flags = CKF_HW;
break;

case CKM_YUBICO_AES_CCM_WRAP:
pInfo->ulMaxKeySize = 256;
pInfo->ulMinKeySize = 128;
Expand All @@ -675,7 +666,10 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
break;

case CKM_AES_KEY_GEN:
find_minmax_aes_key_length_in_bytes(slot->algorithms, slot->n_algorithms,
find_minmax_aes_key_length_in_bytes(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_GENERATE;
Expand All @@ -684,12 +678,25 @@ CK_RV get_mechanism_info(yubihsm_pkcs11_slot *slot, CK_MECHANISM_TYPE type,
case CKM_AES_ECB:
case CKM_AES_CBC:
case CKM_AES_CBC_PAD:
find_minmax_aes_key_length_in_bytes(slot->algorithms, slot->n_algorithms,
find_minmax_aes_key_length_in_bytes(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT;
break;

case CKM_AES_KEY_WRAP_KWP:
find_minmax_aes_key_length_in_bytes(slot->connector->device_info
.algorithms,
slot->connector->device_info
.n_algorithms,
&pInfo->ulMinKeySize,
&pInfo->ulMaxKeySize);
pInfo->flags = CKF_HW;
break;

default:
DBG_ERR("Invalid mechanism %lu", type);
return CKR_MECHANISM_INVALID;
Expand Down
20 changes: 4 additions & 16 deletions pkcs11/yubihsm_pkcs11.c
Original file line number Diff line number Diff line change
Expand Up @@ -687,28 +687,14 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)
memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
memcpy((char *) pInfo->manufacturerID, s, l);

uint8_t major = 0;
uint8_t minor = 0;
uint8_t patch = 0;
uint32_t serial = 0;

yh_rc yrc = yh_util_get_device_info(slot->connector, &major, &minor, &patch,
&serial, NULL, NULL, NULL, NULL);
if (yrc != YHR_SUCCESS) {
DBG_ERR("Unable to get device version and serial number: %s",
yh_strerror(yrc));
rv = yrc_to_rv(yrc);
goto c_gt_out;
}

s = "YubiHSM";
l = strlen(s);
memset(pInfo->model, ' ', sizeof(pInfo->model));
memcpy((char *) pInfo->model, s, l);

memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber));
l = snprintf((char *) pInfo->serialNumber, sizeof(pInfo->serialNumber),
"%08u", serial);
"%08u", slot->connector->device_info.serial);
pInfo->serialNumber[l] = ' ';

pInfo->flags = CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED |
Expand Down Expand Up @@ -737,7 +723,9 @@ CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)
pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;

CK_VERSION ver = {major, (minor * 10) + patch};
CK_VERSION ver = {slot->connector->device_info.major,
(slot->connector->device_info.minor * 10) +
slot->connector->device_info.patch};

pInfo->hardwareVersion = ver;

Expand Down
2 changes: 0 additions & 2 deletions pkcs11/yubihsm_pkcs11.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,6 @@ typedef struct {
yh_session *device_session;
List pkcs11_sessions;
yubihsm_pkcs11_object_desc objects[YH_MAX_ITEMS_COUNT];
yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT];
size_t n_algorithms;
void *mutex;
} yubihsm_pkcs11_slot;

Expand Down
Loading

0 comments on commit d1f325f

Please sign in to comment.