Skip to content

Commit 52f9c03

Browse files
committed
Merge branch 'private/more_bounds'
2 parents 1bbe574 + a2d66a9 commit 52f9c03

File tree

10 files changed

+131
-73
lines changed

10 files changed

+131
-73
lines changed

CHANGELOG

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
=== Version 2.0.3
2+
3+
all: Move away from archaic offensive terms
4+
all: Update build scripts to account for changes in newer MACOS
5+
all: Build on Windows with Visual Studio 2019
6+
pkcs11: Enable .Net to load yubihsm-pkcs11.dylib
7+
lib: Fix memory leaks
8+
lib: Security fixes
9+
lib: Add a session identifier for the backend
10+
lib: Make the backend more thread-safe on Windows
11+
shell: Honor the base64 format when returning a public key
12+
shell: Honor the PEM format when returning a certificate
13+
shell: Improve parsing of command line arguments when using OAEP decryption
14+
shell: Add support for special (national) characters
15+
test: Improve testing
16+
117
=== Version 2.0.2
218

319
yhauth: Report touch policy as part of the "list" command

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ endif ()
9595

9696
set (yubihsm_shell_VERSION_MAJOR 2)
9797
set (yubihsm_shell_VERSION_MINOR 0)
98-
set (yubihsm_shell_VERSION_PATCH 2)
98+
set (yubihsm_shell_VERSION_PATCH 3)
9999
set (VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}")
100100

101101
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
@@ -263,4 +263,4 @@ message(" Libraries ${YUBIHSM_INSTALL_LIB_DIR}")
263263
message(" Includes ${YUBIHSM_INSTALL_INC_DIR}")
264264
message(" Binaries ${YUBIHSM_INSTALL_BIN_DIR}")
265265
message(" Manuals ${YUBIHSM_INSTALL_MAN_DIR}")
266-
message(" Pkg-config ${YUBIHSM_INSTALL_PKGCONFIG_DIR}")
266+
message(" Pkg-config ${YUBIHSM_INSTALL_PKGCONFIG_DIR}")

common/util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,10 +557,10 @@ bool base64_decode(const char *in, uint8_t *out, size_t *len) {
557557
bool hex_decode(const char *in, uint8_t *out, size_t *len) {
558558
int pos = 0;
559559
size_t in_len = strlen(in);
560-
if (in[in_len - 1] == '\n') {
560+
if (in_len > 0 && in[in_len - 1] == '\n') {
561561
in_len--;
562562
}
563-
if (in[in_len - 1] == '\r') {
563+
if (in_len > 0 && in[in_len - 1] == '\r') {
564564
in_len--;
565565
}
566566
if (in_len % 2 != 0) {

lib/yubihsm.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,11 @@ static yh_rc _send_secure_msg(yh_session *session, yh_cmd cmd,
307307
decrypted_data[0] = cmd;
308308
decrypted_data[1] = (data_len & 0xff00) >> 8;
309309
decrypted_data[2] = data_len & 0x00ff;
310-
memcpy(decrypted_data + 3, data, data_len);
310+
if (data != NULL) {
311+
// NOTE(adma): when data_len is 0, data can be NULL. This is UB for
312+
// memcpy. Explicitly check against that
313+
memcpy(decrypted_data + 3, data, data_len);
314+
}
311315
work_buf_len = 3 + data_len;
312316

313317
DBG_DUMPINFO(decrypted_data, data_len + 3,
@@ -357,6 +361,12 @@ static yh_rc _send_secure_msg(yh_session *session, yh_cmd cmd,
357361

358362
// Response is MAC'ed and encrypted. Unwrap it
359363
out_len = response_msg.st.len;
364+
if (out_len < SCP_MAC_LEN - 3 ||
365+
(size_t)(3 + out_len - SCP_MAC_LEN) >= sizeof(work_buf)) {
366+
DBG_ERR("Received invalid length %u", out_len);
367+
yrc = YHR_BUFFER_TOO_SMALL;
368+
goto cleanup;
369+
}
360370

361371
memcpy(work_buf, session->s.mac_chaining_value, SCP_PRF_LEN);
362372
response_msg.st.len = htons(response_msg.st.len);
@@ -709,6 +719,11 @@ yh_rc yh_create_session(yh_connector *connector, uint16_t authkey_id,
709719

710720
// Save sid
711721
new_session->s.sid = (*ptr++);
722+
if (new_session->s.sid > YH_MAX_SESSIONS - 1) {
723+
DBG_ERR("Received invalid session ID %d", new_session->s.sid);
724+
yrc = YHR_GENERIC_ERROR;
725+
goto cs_failure;
726+
}
712727

713728
// Save card challenge
714729
memcpy(new_session->context + SCP_HOST_CHAL_LEN, ptr, SCP_CARD_CHAL_LEN);

lib/yubihsm.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,8 +1489,9 @@ yh_rc yh_util_decrypt_pkcs1v1_5(yh_session *session, uint16_t key_id,
14891489
* @param in_len Length of encrypted data. Must be 256, 384 or 512
14901490
* @param out Decrypted data
14911491
* @param out_len Length of decrypted data
1492-
* @param label OAEP label
1493-
* @param label_len Length of OAEP label. Must be 20, 32, 48 or 64
1492+
* @param label Hash of OAEP label. Hash function must be SHA-1, SHA-256,
1493+
*SHA-384 or SHA-512
1494+
* @param label_len Length of hash of OAEP label. Must be 20, 32, 48 or 64
14941495
* @param mgf1Algo MGF1 algorithm
14951496
*
14961497
* @return #YHR_SUCCESS if successful.

pkcs11/util_pkcs11.c

Lines changed: 45 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "debug_p11.h"
4040
#include "../common/util.h"
4141
#include "../common/openssl-compat.h"
42+
#include "../common/insecure_memzero.h"
4243

4344
#ifdef _MSVC
4445
#define gettimeofday(a, b) gettimeofday_win(a)
@@ -1459,33 +1460,22 @@ static CK_RV get_attribute_public_key(CK_ATTRIBUTE_TYPE type,
14591460
return CKR_OK;
14601461
}
14611462

1462-
CK_RV get_attribute(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object,
1463-
CK_VOID_PTR value, CK_ULONG_PTR length,
1464-
yh_session *session) {
1465-
1466-
CK_BYTE tmp[2048];
1467-
CK_VOID_PTR ptr;
1468-
if (value == NULL) {
1469-
// NOTE(adma): we just need the length, use a scratchpad for the data
1470-
ptr = tmp;
1471-
*length = sizeof(tmp);
1472-
} else {
1473-
// NOTE(adma): otherwise actually save the data
1474-
ptr = value;
1475-
}
1463+
static CK_RV get_attribute(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object,
1464+
CK_BYTE_PTR value, CK_ULONG_PTR length,
1465+
yh_session *session) {
14761466

14771467
switch (object->type) {
14781468
case YH_OPAQUE:
1479-
return get_attribute_opaque(type, object, ptr, length, session);
1469+
return get_attribute_opaque(type, object, value, length, session);
14801470

14811471
case YH_WRAP_KEY:
14821472
case YH_HMAC_KEY:
1483-
return get_attribute_secret_key(type, object, ptr, length);
1473+
return get_attribute_secret_key(type, object, value, length);
14841474

14851475
case YH_ASYMMETRIC_KEY:
1486-
return get_attribute_private_key(type, object, ptr, length, session);
1476+
return get_attribute_private_key(type, object, value, length, session);
14871477
case 0x80 | YH_ASYMMETRIC_KEY:
1488-
return get_attribute_public_key(type, object, ptr, length, session);
1478+
return get_attribute_public_key(type, object, value, length, session);
14891479

14901480
case YH_TEMPLATE:
14911481
case YH_AUTHENTICATION_KEY:
@@ -1497,50 +1487,43 @@ CK_RV get_attribute(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object,
14971487
return CKR_OK;
14981488
}
14991489

1500-
CK_RV get_attribute_ecsession_key(CK_ATTRIBUTE_TYPE type, ecdh_session_key *key,
1501-
CK_VOID_PTR value, CK_ULONG_PTR length) {
1502-
1503-
CK_BYTE tmp[2048];
1504-
CK_VOID_PTR ptr;
1505-
if (value == NULL) {
1506-
ptr = tmp;
1507-
*length = sizeof(tmp);
1508-
} else {
1509-
ptr = value;
1510-
}
1490+
static CK_RV get_attribute_ecsession_key(CK_ATTRIBUTE_TYPE type,
1491+
ecdh_session_key *key,
1492+
CK_BYTE_PTR value,
1493+
CK_ULONG_PTR length) {
15111494

15121495
switch (type) {
15131496
case CKA_CLASS:
1514-
*((CK_OBJECT_CLASS *) ptr) = CKO_SECRET_KEY;
1497+
*((CK_OBJECT_CLASS *) value) = CKO_SECRET_KEY;
15151498
*length = sizeof(CK_OBJECT_CLASS);
15161499
break;
15171500

15181501
case CKA_KEY_TYPE:
1519-
*((CK_KEY_TYPE *) ptr) = CKK_GENERIC_SECRET;
1502+
*((CK_KEY_TYPE *) value) = CKK_GENERIC_SECRET;
15201503
*length = sizeof(CK_KEY_TYPE);
15211504
break;
15221505

15231506
case CKA_ID: {
1524-
CK_OBJECT_HANDLE *id = ptr;
1507+
CK_OBJECT_HANDLE *id = (CK_OBJECT_HANDLE *) value;
15251508
*id = key->id;
15261509
*length = sizeof(CK_OBJECT_HANDLE);
15271510
break;
15281511
}
15291512

15301513
case CKA_LABEL:
15311514
*length = strlen(key->label);
1532-
memcpy(ptr, key->label, *length);
1515+
memcpy(value, key->label, *length);
15331516
break;
15341517

15351518
case CKA_LOCAL:
15361519
case CKA_TOKEN:
1537-
*((CK_BBOOL *) ptr) = CK_FALSE;
1520+
*((CK_BBOOL *) value) = CK_FALSE;
15381521
*length = sizeof(CK_BBOOL);
15391522
break;
15401523

15411524
case CKA_DESTROYABLE:
15421525
case CKA_EXTRACTABLE:
1543-
*((CK_BBOOL *) ptr) = CK_TRUE;
1526+
*((CK_BBOOL *) value) = CK_TRUE;
15441527
*length = sizeof(CK_BBOOL);
15451528
break;
15461529

@@ -1558,12 +1541,12 @@ CK_RV get_attribute_ecsession_key(CK_ATTRIBUTE_TYPE type, ecdh_session_key *key,
15581541
case CKA_WRAP_WITH_TRUSTED:
15591542
case CKA_VERIFY:
15601543
case CKA_ENCRYPT:
1561-
*((CK_BBOOL *) ptr) = CK_FALSE;
1544+
*((CK_BBOOL *) value) = CK_FALSE;
15621545
*length = sizeof(CK_BBOOL);
15631546
break;
15641547

15651548
case CKA_VALUE:
1566-
memcpy(ptr, key->ecdh_key, key->len);
1549+
memcpy(value, key->ecdh_key, key->len);
15671550
*length = key->len;
15681551
break;
15691552

@@ -3879,31 +3862,37 @@ CK_RV populate_template(int type, void *object, CK_ATTRIBUTE_PTR pTemplate,
38793862
CK_ULONG ulCount, yh_session *session) {
38803863

38813864
CK_RV rv = CKR_OK;
3865+
CK_BYTE tmp[8192];
38823866

38833867
for (CK_ULONG i = 0; i < ulCount; i++) {
38843868
DBG_INFO("Getting attribute 0x%lx", pTemplate[i].type);
3885-
3886-
CK_VOID_PTR object_ptr;
3887-
if (pTemplate[i].pValue == NULL) {
3888-
// NOTE(adma): just asking for the length
3889-
object_ptr = NULL;
3890-
DBG_INFO("Retrieving length");
3891-
} else {
3892-
// NOTE(adma): actually get the attribute
3893-
object_ptr = pTemplate[i].pValue;
3894-
DBG_INFO("Retrieving attribute");
3895-
}
3896-
3869+
CK_ULONG len = sizeof(tmp);
38973870
CK_RV attribute_rc;
3871+
38983872
if (type == ECDH_KEY_TYPE) {
38993873
ecdh_session_key *key = object;
39003874
attribute_rc =
3901-
get_attribute_ecsession_key(pTemplate[i].type, key, object_ptr,
3902-
&pTemplate[i].ulValueLen);
3875+
get_attribute_ecsession_key(pTemplate[i].type, key, tmp, &len);
39033876
} else {
39043877
yubihsm_pkcs11_object_desc *desc = object;
3905-
attribute_rc = get_attribute(pTemplate[i].type, &desc->object, object_ptr,
3906-
&pTemplate[i].ulValueLen, session);
3878+
attribute_rc =
3879+
get_attribute(pTemplate[i].type, &desc->object, tmp, &len, session);
3880+
}
3881+
3882+
if (attribute_rc == CKR_OK) {
3883+
if (pTemplate[i].pValue == NULL) {
3884+
DBG_INFO("Retrieving only length which is %lu", len);
3885+
pTemplate[i].ulValueLen = len;
3886+
} else if (len > pTemplate[i].ulValueLen) {
3887+
DBG_WARN("Skipping attribute, buffer to small %lu > %lu", len,
3888+
pTemplate[i].ulValueLen);
3889+
attribute_rc = CKR_BUFFER_TOO_SMALL;
3890+
pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION;
3891+
} else {
3892+
DBG_INFO("Retrieving attribute value, length is %lu", len);
3893+
memcpy(pTemplate[i].pValue, tmp, len);
3894+
pTemplate[i].ulValueLen = len;
3895+
}
39073896
}
39083897

39093898
if (attribute_rc != CKR_OK) {
@@ -3913,7 +3902,7 @@ CK_RV populate_template(int type, void *object, CK_ATTRIBUTE_PTR pTemplate,
39133902
} else if (attribute_rc == CKR_BUFFER_TOO_SMALL) {
39143903
DBG_ERR("Skipping attribute because buffer is too small");
39153904
} else {
3916-
DBG_ERR("Get attribute failed. %s", yh_strerror(attribute_rc));
3905+
DBG_ERR("Get attribute failed.");
39173906
}
39183907
} else {
39193908
DBG_INFO("Attribute/length successfully returned with length %lu",
@@ -3940,6 +3929,8 @@ CK_RV populate_template(int type, void *object, CK_ATTRIBUTE_PTR pTemplate,
39403929
* type having the CKF_ARRAY_ATTRIBUTE bit set.*/
39413930
}
39423931

3932+
insecure_memzero(tmp, sizeof(tmp));
3933+
39433934
return rv;
39443935
}
39453936

pkcs11/util_pkcs11.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ bool parse_hex(CK_UTF8CHAR_PTR hex, CK_ULONG hex_len, uint8_t *parsed);
3333

3434
void destroy_session(yubihsm_pkcs11_context *ctx, CK_SESSION_HANDLE hSession);
3535

36-
CK_RV get_attribute(CK_ATTRIBUTE_TYPE type, yh_object_descriptor *object,
37-
CK_VOID_PTR value, CK_ULONG_PTR length,
38-
yh_session *session);
39-
CK_RV get_attribute_ecsession_key(CK_ATTRIBUTE_TYPE type, ecdh_session_key *key,
40-
CK_VOID_PTR value, CK_ULONG_PTR length);
41-
4236
yubihsm_pkcs11_object_desc *get_object_desc(yh_session *session,
4337
yubihsm_pkcs11_object_desc *objects,
4438
CK_OBJECT_HANDLE objectHandle);

src/README.adoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ For the most part it is a thin wrapper around `libyubihsm` exposing
66
most of its functions directly to the user.
77

88
YubiHSM Shell can be invoked in interactive mode and from the command
9-
line.
9+
line. Special (national) characters are supported on MacOS and Linux
10+
platforms. On Windows, they are supported in interactive mode and the
11+
same support can be activated through the OpenSSL environment variable
12+
`OPENSSL_WIN32_UTF8` for interactive password entry in non-interactive
13+
mode (i.e if password is not given on the command line). Such characters
14+
will be encoded according to current locale settings on MacOS/Linux
15+
(typically utf-8), and always as utf-8 on Windows.
1016

1117
=== Interactive Mode
1218

src/commands.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ int yh_com_audit(yubihsm_context *ctx, Argument *argv, cmd_format fmt) {
7676
uint16_t unlogged_boot = 0;
7777
uint16_t unlogged_auth = 0;
7878
yh_log_entry logs[YH_MAX_LOG_ENTRIES];
79-
size_t n_items = sizeof(logs);
79+
size_t n_items = sizeof(logs) / sizeof(logs[0]);
8080

8181
switch (fmt) {
8282
case fmt_binary:
@@ -2773,8 +2773,8 @@ int yh_com_generate_otp_aead_key(yubihsm_context *ctx, Argument *argv,
27732773
// arg 0: e:session
27742774
// arg 1: w:key_id
27752775
// arg 2: a:algorithm
2776-
// arg 3: s:label
2777-
// arg 4: f:datafile
2776+
// arg 3: f:datafile
2777+
// arg 4: s:label
27782778
int yh_com_decrypt_oaep(yubihsm_context *ctx, Argument *argv, cmd_format fmt) {
27792779

27802780
yh_rc yrc;
@@ -2814,7 +2814,8 @@ int yh_com_decrypt_oaep(yubihsm_context *ctx, Argument *argv, cmd_format fmt) {
28142814
return -1;
28152815
}
28162816

2817-
if (hash_bytes(argv[4].x, argv[4].len, hash, label, &label_len) == false) {
2817+
if (hash_bytes((const uint8_t *) argv[4].s, argv[4].len, hash, label,
2818+
&label_len) == false) {
28182819
fprintf(stderr, "Unable to hash data\n");
28192820
return -1;
28202821
}

0 commit comments

Comments
 (0)