Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constant time RSA PKCS#1 v1.5 depadding #2948

Merged
merged 8 commits into from
Feb 5, 2024
Prev Previous commit
Next Next commit
Add unit tests for PKCS#1 v1.5 de-padding
  • Loading branch information
xhanulik committed Jan 31, 2024
commit 708ce24c6b9f92a9f39bb7accda601b2891304a3
7 changes: 5 additions & 2 deletions src/tests/unittests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ VALGRIND_FLAGS = --num-callers=30 -q --keep-debuginfo=yes --gen-suppressions=all
TESTS_ENVIRONMENT = LD_PRELOAD='/usr/lib/x86_64-linux-gnu/libpcsclite.so.1'
endif

noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature check_macro_reference_loop
TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin decode_ecdsa_signature check_macro_reference_loop
noinst_PROGRAMS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
decode_ecdsa_signature check_macro_reference_loop strip_pkcs1_2_padding
TESTS = asn1 simpletlv cachedir pkcs15filter openpgp-tool hextobin \
decode_ecdsa_signature check_macro_reference_loop strip_pkcs1_2_padding

noinst_HEADERS = torture.h

Expand All @@ -37,6 +39,7 @@ openpgp_tool_SOURCES = openpgp-tool.c $(top_builddir)/src/tools/openpgp-tool-hel
hextobin_SOURCES = hextobin.c
decode_ecdsa_signature_SOURCES = decode_ecdsa_signature.c
check_macro_reference_loop = check_macro_reference_loop.c
strip_pkcs1_2_padding = strip_pkcs1_2_padding.c

if ENABLE_ZLIB
noinst_PROGRAMS += compression
Expand Down
5 changes: 3 additions & 2 deletions src/tests/unittests/Makefile.mak
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
TOPDIR = ..\..\..

TARGETS = asn1 compression pkcs15filter check_macro_reference_loop
TARGETS = asn1 compression pkcs15filter check_macro_reference_loop strip_pkcs1_2_padding

OBJECTS = asn1.obj \
compression.obj \
pkcs15-emulator-filter.obj \
check_macro_reference_loop.obj
check_macro_reference_loop.obj \
strip_pkcs1_2_padding.obj \
$(TOPDIR)\win32\versioninfo.res

all: $(TARGETS)
Expand Down
204 changes: 204 additions & 0 deletions src/tests/unittests/strip_pkcs1_2_padding.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
#include "common/compat_strlcpy.c"
#include "libopensc/log.c"
#include "libopensc/padding.c"
#include "torture.h"
#include <cmocka.h>

static void
torture_long_output_buffer(void **state)
{
unsigned int n = 14;
unsigned int in_len = 14;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00,
'm', 's', 'g'};
unsigned int out_len = 3;
unsigned char *out = malloc(out_len * sizeof(unsigned char));
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_memory_equal(out, result_msg, r);
free(out);
}

static void
torture_short_output_buffer(void **state)
{
unsigned int n = 14;
unsigned int in_len = 14;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00,
'm', 's', 'g'};
unsigned int out_len = 1;
unsigned char *out = malloc(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(r, SC_ERROR_WRONG_PADDING);
free(out);
}

static void
torture_short_message_correct_padding(void **state)
{
unsigned int n = 14;
unsigned int in_len = 14;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00,
'm', 's', 'g'};
unsigned int out_len = 3;
unsigned char *out = malloc(out_len * sizeof(unsigned char));
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_memory_equal(out, result_msg, r);
free(out);
}

static void
torture_missing_first_zero(void **state)
{
unsigned int n = 13;
unsigned int in_len = 13;
unsigned char in[] = {0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00,
'm', 's', 'g'};
unsigned int out_len = 10;
unsigned char *out = malloc(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(r, SC_ERROR_WRONG_PADDING);
free(out);
}

static void
torture_missing_two(void **state)
{
unsigned int n = 13;
unsigned int in_len = 13;
unsigned char in[] = {0x00,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00,
'm', 's', 'g'};
unsigned int out_len = 10;
unsigned char *out = malloc(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(r, SC_ERROR_WRONG_PADDING);
free(out);
}

static void
torture_short_padding(void **state)
{
unsigned int n = 13;
unsigned int in_len = 13;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00,
'm', 's', 'g'};
unsigned int out_len = 10;
unsigned char *out = malloc(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(r, SC_ERROR_WRONG_PADDING);
free(out);
}

static void
torture_missing_second_zero(void **state)
{
unsigned int n = 13;
unsigned int in_len = 13;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
'm', 's', 'g'};
unsigned int out_len = 10;
unsigned char *out = malloc(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(r, SC_ERROR_WRONG_PADDING);
free(out);
}

static void
torture_missing_message(void **state)
{
unsigned int n = 20;
unsigned int in_len = 11;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00};
unsigned int out_len = 11;
unsigned char *out = malloc(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(r, SC_ERROR_WRONG_PADDING);
free(out);
}

static void
torture_one_byte_message(void **state)
{
unsigned int n = 12;
unsigned int in_len = 12;
unsigned char in[] = {0x00, 0x02,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x00,
'm'};
unsigned int out_len = 1;
unsigned char *out = malloc(out_len * sizeof(unsigned char));
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_memory_equal(out, result_msg, r);
free(out);
}

static void
torture_longer_padding(void **state)
{
unsigned int n = 26;
unsigned int in_len = 26;
unsigned char in[] = {0x00, 0x02,
0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
0x00,
0x9d, 0x98, 0x3d, 0xca, 0xa9, 0xa7, 0x11, 0x0a};
unsigned int out_len = 8;
unsigned char *out = malloc(out_len * sizeof(unsigned char));
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_memory_equal(out, result_msg, r);
free(out);
}

static void
torture_empty_message(void **state)
{
unsigned int n = 18;
unsigned int in_len = 18;
unsigned char in[] = {0x00, 0x02,
0x0e, 0x38, 0x97, 0x18, 0x16, 0x57, 0x9e, 0x30, 0xb6, 0xa5, 0x78, 0x13, 0x20, 0xca, 0x11,
0x00};
unsigned int out_len = 8;
unsigned char *out = malloc(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(r, 0);
free(out);
}

int
main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(torture_long_output_buffer),
cmocka_unit_test(torture_short_output_buffer),
cmocka_unit_test(torture_short_message_correct_padding),
cmocka_unit_test(torture_missing_first_zero),
cmocka_unit_test(torture_missing_two),
cmocka_unit_test(torture_short_padding),
cmocka_unit_test(torture_missing_second_zero),
cmocka_unit_test(torture_missing_message),
cmocka_unit_test(torture_one_byte_message),
cmocka_unit_test(torture_longer_padding),
cmocka_unit_test(torture_empty_message)};
return cmocka_run_group_tests(tests, NULL, NULL);
}