#include <stdint.h>
#include <string.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#if 0
static void
hexdump(const unsigned char *buf, size_t len)
{
size_t i;
for (i = 1; i <= len; i++)
fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
fprintf(stderr, "\n");
}
#endif
struct pkcs1_test {
uint8_t in[128];
size_t in_len;
int want;
int want_error;
};
static const struct pkcs1_test pkcs1_type1_tests[] = {
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
},
.in_len = 32,
.want = 19,
},
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00,
},
.in_len = 11,
.want = 0,
},
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff,
},
.in_len = 12,
.want = 1,
},
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0xff, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BAD_PAD_BYTE_COUNT,
},
{
.in = {
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BLOCK_TYPE_IS_NOT_01,
},
{
.in = {
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BLOCK_TYPE_IS_NOT_01,
},
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0x00, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BAD_FIXED_HEADER_DECRYPT,
},
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
},
.in_len = 32,
.want = -1,
.want_error = RSA_R_NULL_BEFORE_BLOCK_MISSING,
},
};
#define N_PKCS1_TYPE1_TESTS \
(sizeof(pkcs1_type1_tests) / sizeof(pkcs1_type1_tests[0]))
static int
test_pkcs1_type1(void)
{
const struct pkcs1_test *pt;
uint8_t buf[32], in[19], out[512];
int pad_len;
long err;
size_t i;
int failed = 1;
for (i = 0; i < 1000; i++) {
arc4random_buf(in, sizeof(in));
if (!RSA_padding_add_PKCS1_type_1(buf, sizeof(buf), in,
sizeof(in))) {
fprintf(stderr, "FAIL: failed to add PKCS1 type 1 "
"padding\n");
goto failed;
}
pad_len = RSA_padding_check_PKCS1_type_1(out, sizeof(out) - 1,
buf + 1, sizeof(buf) - 1, sizeof(buf));
if (pad_len != sizeof(in)) {
fprintf(stderr, "FAIL: failed to check PKCS1 type 1 "
"padding\n");
ERR_print_errors_fp(stderr);
goto failed;
}
}
for (i = 0; i < N_PKCS1_TYPE1_TESTS; i++) {
pt = &pkcs1_type1_tests[i];
ERR_clear_error();
pad_len = RSA_padding_check_PKCS1_type_1(out, sizeof(out) - 1,
pt->in + 1, pt->in_len - 1, pt->in_len);
if (pad_len != pt->want) {
fprintf(stderr, "FAIL: test %zu - failed to check "
"PKCS1 type 1 padding (%d != %d)\n", i, pad_len,
pt->want);
ERR_print_errors_fp(stderr);
goto failed;
}
err = ERR_peek_error();
if (pt->want == -1 && ERR_GET_REASON(err) != pt->want_error) {
fprintf(stderr, "FAIL: test %zu - PKCS1 type 1 padding "
"check failed with error reason %i, want %i\n",
i, ERR_GET_REASON(err), pt->want_error);
ERR_print_errors_fp(stderr);
goto failed;
}
}
failed = 0;
failed:
return failed;
}
static const struct pkcs1_test pkcs1_type2_tests[] = {
{
.in = {
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
},
.in_len = 32,
.want = 19,
},
{
.in = {
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00,
},
.in_len = 11,
.want = 0,
},
{
.in = {
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff,
},
.in_len = 12,
.want = 1,
},
{
.in = {
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0x00, 0xff, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BAD_PAD_BYTE_COUNT,
},
{
.in = {
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BLOCK_TYPE_IS_NOT_02,
},
{
.in = {
0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0x00, 0xff,
},
.in_len = 12,
.want = -1,
.want_error = RSA_R_BLOCK_TYPE_IS_NOT_02,
},
{
.in = {
0x00, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
},
.in_len = 32,
.want = -1,
.want_error = RSA_R_NULL_BEFORE_BLOCK_MISSING,
},
};
#define N_PKCS1_TYPE2_TESTS \
(sizeof(pkcs1_type2_tests) / sizeof(pkcs1_type2_tests[0]))
static int
test_pkcs1_type2(void)
{
const struct pkcs1_test *pt;
uint8_t buf[32], in[19], out[512];
int pad_len;
long err;
size_t i;
int failed = 1;
for (i = 0; i < 1000; i++) {
arc4random_buf(in, sizeof(in));
if (!RSA_padding_add_PKCS1_type_2(buf, sizeof(buf), in,
sizeof(in))) {
fprintf(stderr, "FAIL: failed to add PKCS1 type 2 "
"padding\n");
goto failed;
}
pad_len = RSA_padding_check_PKCS1_type_2(out, sizeof(out) - 1,
buf + 1, sizeof(buf) - 1, sizeof(buf));
if (pad_len != sizeof(in)) {
fprintf(stderr, "FAIL: failed to check PKCS1 type 2 "
"padding\n");
ERR_print_errors_fp(stderr);
goto failed;
}
}
for (i = 0; i < N_PKCS1_TYPE2_TESTS; i++) {
pt = &pkcs1_type2_tests[i];
ERR_clear_error();
pad_len = RSA_padding_check_PKCS1_type_2(out, sizeof(out) - 1,
pt->in + 1, pt->in_len - 1, pt->in_len);
if (pad_len != pt->want) {
fprintf(stderr, "FAIL: test %zu - failed to check "
"PKCS1 type 2 padding (%d != %d)\n", i, pad_len,
pt->want);
ERR_print_errors_fp(stderr);
goto failed;
}
err = ERR_peek_error();
if (pt->want == -1 && ERR_GET_REASON(err) != pt->want_error) {
fprintf(stderr, "FAIL: test %zu - PKCS1 type 2 padding "
"check failed with error reason %i, want %i\n",
i, ERR_GET_REASON(err), pt->want_error);
ERR_print_errors_fp(stderr);
goto failed;
}
}
failed = 0;
failed:
return failed;
}
int
main(int argc, char **argv)
{
int failed = 0;
failed |= test_pkcs1_type1();
failed |= test_pkcs1_type2();
return failed;
}