diff --git a/.appveyor.yml b/.appveyor.yml index 4599100ad2..f5879c4ba4 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,4 @@ -version: 0.25.0.{build} +version: 0.25.1.{build} platform: - x86 @@ -96,8 +96,7 @@ build_script: } - bash -c "exec 0 n || n < SC_PKCS1_PADDING_MIN_SIZE) + if (data == NULL || data_len <= 0 || data_len > n || + n < SC_PKCS1_PADDING_MIN_SIZE || out_len == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); + tmp_outlen = *out_len; msg = msg_orig = calloc(n, sizeof(u8)); if (msg == NULL) LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); @@ -201,18 +203,18 @@ sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const mlen = data_len - msg_index; // check that message fits into out buffer - good &= constant_time_ge(*out_len, mlen); + good &= constant_time_ge(tmp_outlen, mlen); // move the result in-place by |num|-SC_PKCS1_PADDING_MIN_SIZE-|mlen| bytes to the left. - *out_len = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, *out_len), - n - SC_PKCS1_PADDING_MIN_SIZE, *out_len); + tmp_outlen = constant_time_select(constant_time_lt(n - SC_PKCS1_PADDING_MIN_SIZE, tmp_outlen), + n - SC_PKCS1_PADDING_MIN_SIZE, tmp_outlen); for (msg_index = 1; msg_index < n - SC_PKCS1_PADDING_MIN_SIZE; msg_index <<= 1) { mask = ~constant_time_eq(msg_index & (n - SC_PKCS1_PADDING_MIN_SIZE - mlen), 0); for (i = SC_PKCS1_PADDING_MIN_SIZE; i < n - msg_index; i++) msg[i] = constant_time_select_8(mask, msg[i + msg_index], msg[i]); } // move message into out buffer, if good - for (i = 0; i < *out_len; i++) { + for (i = 0; i < tmp_outlen; i++) { unsigned int msg_index; // when out is longer than message in data, use some bogus index in msg mask = good & constant_time_lt(i, mlen); @@ -220,6 +222,7 @@ sc_pkcs1_strip_02_padding_constant_time(sc_context_t *ctx, unsigned int n, const out[i] = constant_time_select_8(mask, msg[msg_index], out[i]); } + *out_len = constant_time_select(good, mlen, *out_len); free(msg_orig); return constant_time_select(good, mlen, SC_ERROR_WRONG_PADDING); } diff --git a/src/minidriver/minidriver.c b/src/minidriver/minidriver.c index 7796afdac2..10da7dba43 100644 --- a/src/minidriver/minidriver.c +++ b/src/minidriver/minidriver.c @@ -513,9 +513,12 @@ get_pin_by_name(PCARD_DATA pCardData, struct sc_pkcs15_card *p15card, int role, if (!conf_block) MD_FUNC_RETURN(pCardData, 1, SCARD_F_INTERNAL_ERROR); - memset(str_path, 0, sizeof(str_path)); - sc_bin_to_hex(p15card->app->path.value, p15card->app->path.len, str_path, sizeof(str_path), 0); - blocks = scconf_find_blocks(p15card->card->ctx->conf, conf_block, "application", str_path); + if (p15card->app != NULL) { + memset(str_path, 0, sizeof(str_path)); + sc_bin_to_hex(p15card->app->path.value, p15card->app->path.len, str_path, sizeof(str_path), 0); + blocks = scconf_find_blocks(p15card->card->ctx->conf, conf_block, "application", str_path); + } + if (blocks) { if (blocks[0]) { pin = (char *)scconf_get_str(blocks[0], pin_type, NULL); @@ -4710,7 +4713,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, goto err; } - good = constant_time_eq_i(r, 0); + good = constant_time_ge(r, 1); /* if no error or padding error, do not return here to prevent Marvin attack */ if (!(good | wrong_padding) && r < 0) { logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r)); @@ -4721,18 +4724,16 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData, } dwret = constant_time_select_s(good, SCARD_S_SUCCESS, SCARD_F_INTERNAL_ERROR); - logprintf(pCardData, 2, "decrypted data(%lu):\n", - (unsigned long)pInfo->cbData); - loghex(pCardData, 7, pbuf2, pInfo->cbData); - /*inversion donnees */ /* copy data in constant-time way to prevent leak */ for (ui = 0; ui < pbufLen; ui++) { - unsigned int mask, msg_index, inv_ui; - mask = good & constant_time_lt_s(ui, pInfo->cbData); /* ui should be in the bounds of pbuf2 */ - inv_ui = pInfo->cbData - ui - 1; - msg_index = constant_time_select_s(mask, inv_ui, 0); - pInfo->pbData[ui] = constant_time_select_8(mask, pbuf2[msg_index], pInfo->pbData[ui]); + unsigned int mask, inv_ui; + unsigned char msg_byte, orig_byte; + mask = good & constant_time_lt_s(ui, pInfo->cbData); /* ui should be in bounds of decrypted message */ + inv_ui = pInfo->cbData - ui - 1; /* compute inversed ui index */ + msg_byte = pbuf2[constant_time_select(mask, inv_ui, 0)]; /* if in range of decrypted message, read on inversed index otherwise read some bogus value */ + orig_byte = pInfo->pbData[ui]; + pInfo->pbData[ui] = constant_time_select_s(mask, msg_byte, orig_byte); /* store message byte only if in correct range */ } pCardData->pfnCspFree(pbuf); diff --git a/src/tests/unittests/strip_pkcs1_2_padding.c b/src/tests/unittests/strip_pkcs1_2_padding.c index 990e94a38b..385841fc59 100644 --- a/src/tests/unittests/strip_pkcs1_2_padding.c +++ b/src/tests/unittests/strip_pkcs1_2_padding.c @@ -18,6 +18,7 @@ torture_long_output_buffer(void **state) unsigned char result_msg[] = {'m', 's', 'g'}; int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); assert_int_equal(r, 3); + assert_int_equal(r, (int)out_len); assert_memory_equal(out, result_msg, r); free(out); } @@ -34,6 +35,7 @@ torture_short_output_buffer(void **state) unsigned int out_len = 1; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 1); assert_int_equal(r, SC_ERROR_WRONG_PADDING); free(out); } @@ -52,6 +54,7 @@ torture_short_message_correct_padding(void **state) unsigned char result_msg[] = {'m', 's', 'g'}; int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); assert_int_equal(r, 3); + assert_int_equal(r, (int)out_len); assert_memory_equal(out, result_msg, r); free(out); } @@ -68,6 +71,7 @@ torture_missing_first_zero(void **state) unsigned int out_len = 10; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 10); assert_int_equal(r, SC_ERROR_WRONG_PADDING); free(out); } @@ -84,6 +88,7 @@ torture_missing_two(void **state) unsigned int out_len = 10; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 10); assert_int_equal(r, SC_ERROR_WRONG_PADDING); free(out); } @@ -100,6 +105,7 @@ torture_short_padding(void **state) unsigned int out_len = 10; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 10); assert_int_equal(r, SC_ERROR_WRONG_PADDING); free(out); } @@ -115,6 +121,7 @@ torture_missing_second_zero(void **state) unsigned int out_len = 10; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 10); assert_int_equal(r, SC_ERROR_WRONG_PADDING); free(out); } @@ -130,6 +137,7 @@ torture_missing_message(void **state) unsigned int out_len = 11; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 11); assert_int_equal(r, SC_ERROR_WRONG_PADDING); free(out); } @@ -148,6 +156,7 @@ torture_one_byte_message(void **state) unsigned char result_msg[] = {'m'}; int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); assert_int_equal(r, 1); + assert_int_equal(r, (int)out_len); assert_memory_equal(out, result_msg, r); free(out); } @@ -166,6 +175,7 @@ torture_longer_padding(void **state) unsigned char result_msg[] = {0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a}; int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); assert_int_equal(r, 8); + assert_int_equal(r, (int)out_len); assert_memory_equal(out, result_msg, r); free(out); } @@ -181,6 +191,7 @@ torture_empty_message(void **state) unsigned int out_len = 8; unsigned char *out = calloc(out_len, sizeof(unsigned char)); int r = sc_pkcs1_strip_02_padding_constant_time(NULL, n, in, in_len, out, &out_len); + assert_int_equal((int)out_len, 0); assert_int_equal(r, 0); free(out); }