You've already forked opencryptoki
mirror of
https://github.com/opencryptoki/opencryptoki.git
synced 2026-10-24 05:39:17 +03:00
TESTCASES: Add unit tests for PKCS#7 padding and unpadding
Test the PKCS#7 padding and unpadding functions to behave correctly on various valid and invalid inputs. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
This commit is contained in:
committed by
Ingo Franzki
parent
594f41b08b
commit
3f6fb6d30b
1
.gitignore
vendored
1
.gitignore
vendored
@@ -74,6 +74,7 @@ testcases/unit/pintest
|
||||
testcases/unit/asn1test
|
||||
testcases/unit/asn1fuzztest
|
||||
testcases/unit/objectflattentest
|
||||
testcases/unit/padtest
|
||||
usr/sbin/p11sak/p11sak
|
||||
usr/sbin/p11kmip/p11kmip
|
||||
usr/sbin/pkcscca/pkcscca
|
||||
|
||||
209
testcases/unit/padtest.c
Normal file
209
testcases/unit/padtest.c
Normal file
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* COPYRIGHT (c) International Business Machines Corp. 2026
|
||||
*
|
||||
* This program is provided under the terms of the Common Public License,
|
||||
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
||||
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
||||
* found in the file LICENSE file or at
|
||||
* https://opensource.org/licenses/cpl1.0.php
|
||||
*/
|
||||
|
||||
/*
|
||||
* Unit test for add_pkcs_padding() and strip_pkcs_padding() in utility.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pkcs11types.h"
|
||||
#include "defs.h"
|
||||
#include "host_defs.h"
|
||||
#include "h_extern.h"
|
||||
#include "unittest.h"
|
||||
|
||||
#define MAX_BUF 256
|
||||
#define FILL_BYTE 0xAA
|
||||
#define LEN_UNTOUCHED ((CK_ULONG)0xDEADBEEF)
|
||||
|
||||
/*
|
||||
* The buffer is built as follows: it is first filled with FILL_BYTE, then the
|
||||
* last 'pad_count' bytes are set to 'pad_value'. Finally, if 'corrupt_idx' is
|
||||
* not 0, the byte 'corrupt_idx' bytes from the end (1 = last byte) is set to
|
||||
* 'corrupt_val'.
|
||||
*/
|
||||
struct strip_test {
|
||||
const char *name;
|
||||
CK_ULONG block_size;
|
||||
CK_ULONG total_len;
|
||||
CK_BYTE pad_value;
|
||||
CK_ULONG pad_count;
|
||||
CK_ULONG corrupt_idx;
|
||||
CK_BYTE corrupt_val;
|
||||
CK_RV exp_rc;
|
||||
CK_ULONG exp_data_len;
|
||||
};
|
||||
|
||||
static const struct strip_test strip_tests[] = {
|
||||
/* valid padding */
|
||||
{ "AES: 1 pad byte", 16, 16, 1, 1, 0, 0, CKR_OK, 15 },
|
||||
{ "AES: 3 pad bytes", 16, 16, 3, 3, 0, 0, CKR_OK, 13 },
|
||||
{ "AES: full padding block", 16, 16, 16, 16, 0, 0, CKR_OK, 0 },
|
||||
{ "AES: full padding block, 2 blocks", 16, 32, 16, 16, 0, 0, CKR_OK, 16 },
|
||||
{ "AES: 15 pad bytes, 2 blocks", 16, 32, 15, 15, 0, 0, CKR_OK, 17 },
|
||||
{ "AES: byte before padding equals pad value", 16, 32, 15, 16, 0, 0,
|
||||
CKR_OK, 17 },
|
||||
{ "DES: full padding block", 8, 8, 8, 8, 0, 0, CKR_OK, 0 },
|
||||
{ "DES: 1 pad byte, 3 blocks", 8, 24, 1, 1, 0, 0, CKR_OK, 23 },
|
||||
|
||||
/* invalid pad value */
|
||||
{ "pad value 0", 16, 16, 0, 1, 0, 0, CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "pad value 0, all bytes 0", 16, 16, 0, 16, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "AES: pad value 17 > block size", 16, 16, 17, 16, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "AES: pad value 32 > block size, 2 blocks", 16, 32, 32, 32, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "DES: pad value 9 > block size", 8, 16, 9, 9, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "pad value 255", 16, 32, 255, 32, 0, 0, CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
|
||||
/* invalid pad bytes */
|
||||
{ "only last byte is the pad value", 16, 16, 3, 1, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "middle pad byte differs", 16, 16, 3, 3, 2, 2,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "first pad byte differs", 16, 16, 4, 4, 4, FILL_BYTE,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "first pad byte of full block differs", 16, 16, 16, 16, 16, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "DES: first pad byte of full block differs", 8, 8, 8, 8, 8, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
|
||||
/* invalid lengths */
|
||||
{ "total length 0", 16, 0, 1, 0, 0, 0, CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "total length not a multiple of block size", 16, 20, 1, 1, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "total length smaller than block size", 16, 8, 1, 1, 0, 0,
|
||||
CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
|
||||
/* invalid block size */
|
||||
{ "block size 0", 0, 16, 1, 1, 0, 0, CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
{ "block size 256", 256, 256, 1, 1, 0, 0, CKR_ENCRYPTED_DATA_INVALID, 0 },
|
||||
};
|
||||
|
||||
static int test_strip_pkcs_padding(void)
|
||||
{
|
||||
const struct strip_test *t;
|
||||
CK_BYTE buf[MAX_BUF];
|
||||
CK_ULONG data_len;
|
||||
CK_RV rc;
|
||||
size_t i;
|
||||
int result = 0, failed;
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(strip_tests); i++) {
|
||||
t = &strip_tests[i];
|
||||
failed = 0;
|
||||
|
||||
memset(buf, FILL_BYTE, sizeof(buf));
|
||||
if (t->pad_count > 0)
|
||||
memset(buf + t->total_len - t->pad_count, t->pad_value,
|
||||
t->pad_count);
|
||||
if (t->corrupt_idx > 0)
|
||||
buf[t->total_len - t->corrupt_idx] = t->corrupt_val;
|
||||
|
||||
data_len = LEN_UNTOUCHED;
|
||||
rc = strip_pkcs_padding(buf, t->block_size, t->total_len, &data_len);
|
||||
|
||||
if (rc != t->exp_rc) {
|
||||
fprintf(stderr, "FAIL: strip [%zu] %s: unexpected rc 0x%lx "
|
||||
"(expected 0x%lx)\n", i, t->name, rc, t->exp_rc);
|
||||
failed = 1;
|
||||
} else if (t->exp_rc == CKR_OK) {
|
||||
if (data_len != t->exp_data_len) {
|
||||
fprintf(stderr, "FAIL: strip [%zu] %s: unexpected data_len "
|
||||
"%lu (expected %lu)\n", i, t->name, data_len,
|
||||
t->exp_data_len);
|
||||
failed = 1;
|
||||
}
|
||||
} else if (data_len != LEN_UNTOUCHED) {
|
||||
fprintf(stderr, "FAIL: strip [%zu] %s: data_len modified on "
|
||||
"failure\n", i, t->name);
|
||||
failed = 1;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
result++;
|
||||
else
|
||||
printf("PASS: strip [%zu] %s\n", i, t->name);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round trip: add_pkcs_padding() followed by strip_pkcs_padding() must return
|
||||
* the original data length for all data lengths and both block sizes.
|
||||
*/
|
||||
static int test_round_trip(void)
|
||||
{
|
||||
static const CK_ULONG block_sizes[] = { 8, 16 };
|
||||
CK_BYTE buf[MAX_BUF];
|
||||
CK_ULONG bs, data_len, total_len, out_len;
|
||||
CK_RV rc;
|
||||
size_t i;
|
||||
int result = 0, failed;
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(block_sizes); i++) {
|
||||
bs = block_sizes[i];
|
||||
failed = 0;
|
||||
|
||||
for (data_len = 0; data_len <= 3 * bs; data_len++) {
|
||||
total_len = bs * (data_len / bs + 1);
|
||||
|
||||
memset(buf, FILL_BYTE, sizeof(buf));
|
||||
rc = add_pkcs_padding(buf + data_len, bs, data_len, total_len);
|
||||
if (rc != CKR_OK) {
|
||||
fprintf(stderr, "FAIL: round trip (bs=%lu, len=%lu): "
|
||||
"add_pkcs_padding rc 0x%lx\n", bs, data_len, rc);
|
||||
failed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
out_len = LEN_UNTOUCHED;
|
||||
rc = strip_pkcs_padding(buf, bs, total_len, &out_len);
|
||||
if (rc != CKR_OK || out_len != data_len) {
|
||||
fprintf(stderr, "FAIL: round trip (bs=%lu, len=%lu): "
|
||||
"strip_pkcs_padding rc 0x%lx, out_len %lu\n",
|
||||
bs, data_len, rc, out_len);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
result += failed;
|
||||
if (failed == 0)
|
||||
printf("PASS: round trip, block size %lu, data lengths 0..%lu\n",
|
||||
bs, 3 * bs);
|
||||
else
|
||||
fprintf(stderr, "FAIL: round trip, block size %lu, data lengths "
|
||||
"0..%lu: %d failure(s)\n", bs, 3 * bs, failed);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test_strip_pkcs_padding();
|
||||
result += test_round_trip();
|
||||
|
||||
if (result != 0) {
|
||||
fprintf(stderr, "padtest: %d failure(s)\n", result);
|
||||
return TEST_FAIL;
|
||||
}
|
||||
|
||||
printf("padtest: all tests passed\n");
|
||||
|
||||
return TEST_PASS;
|
||||
}
|
||||
156
testcases/unit/padtest_stubs.c
Normal file
156
testcases/unit/padtest_stubs.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* COPYRIGHT (c) International Business Machines Corp. 2026
|
||||
*
|
||||
* This program is provided under the terms of the Common Public License,
|
||||
* version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
|
||||
* software constitutes recipient's acceptance of CPL-1.0 terms which can be
|
||||
* found in the file LICENSE file or at
|
||||
* https://opensource.org/licenses/cpl1.0.php
|
||||
*/
|
||||
|
||||
/*
|
||||
* Stub implementations for padtest
|
||||
* These stubs satisfy the external references of utility.c, which is linked
|
||||
* into padtest to test add_pkcs_padding() and strip_pkcs_padding(). None of
|
||||
* the stubbed functions is called by the code under test.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pkcs11types.h"
|
||||
#include "defs.h"
|
||||
#include "host_defs.h"
|
||||
#include "h_extern.h"
|
||||
#include "p11util.h"
|
||||
#include "attributes.h"
|
||||
#include "shared_memory.h"
|
||||
|
||||
/* Global data */
|
||||
token_spec_t token_specific = { 0 };
|
||||
|
||||
const char manuf[] = "IBM";
|
||||
const char model[] = "PadTest";
|
||||
const char descr[] = "IBM padtest";
|
||||
const char label[] = "padtest";
|
||||
|
||||
const CK_BYTE default_so_pin_sha[SHA1_HASH_SIZE] = { 0 };
|
||||
const CK_BYTE default_so_pin_md5[MD5_HASH_SIZE] = { 0 };
|
||||
|
||||
/* loadsave.c */
|
||||
CK_RV generate_master_key(STDLL_TokData_t *tokdata, CK_BYTE *key)
|
||||
{
|
||||
(void)tokdata;
|
||||
(void)key;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
CK_RV save_masterkey_so(STDLL_TokData_t *tokdata)
|
||||
{
|
||||
(void)tokdata;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
CK_RV save_token_data(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id)
|
||||
{
|
||||
(void)tokdata;
|
||||
(void)slot_id;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
char *get_pk_dir(STDLL_TokData_t *tokdata, char *fname, size_t len)
|
||||
{
|
||||
(void)tokdata;
|
||||
(void)fname;
|
||||
(void)len;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* mech_rng.c */
|
||||
CK_RV rng_generate(STDLL_TokData_t *tokdata, CK_BYTE *output, CK_ULONG bytes)
|
||||
{
|
||||
(void)tokdata;
|
||||
(void)output;
|
||||
(void)bytes;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* shared_memory.c */
|
||||
int sm_open(const char *sm_name, int mode, void **p_addr, size_t len,
|
||||
int force, const char *group)
|
||||
{
|
||||
(void)sm_name;
|
||||
(void)mode;
|
||||
(void)p_addr;
|
||||
(void)len;
|
||||
(void)force;
|
||||
(void)group;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int sm_close(void *addr, int destroy, int ignore_ref_count)
|
||||
{
|
||||
(void)addr;
|
||||
(void)destroy;
|
||||
(void)ignore_ref_count;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* obj_mgr.c */
|
||||
CK_RV object_mgr_find_in_map1(STDLL_TokData_t *tokdata,
|
||||
CK_OBJECT_HANDLE handle, OBJECT **ptr,
|
||||
OBJ_LOCK_TYPE lock_type)
|
||||
{
|
||||
(void)tokdata;
|
||||
(void)handle;
|
||||
(void)ptr;
|
||||
(void)lock_type;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
CK_RV object_put(STDLL_TokData_t *tokdata, OBJECT *obj, CK_BBOOL unlock)
|
||||
{
|
||||
(void)tokdata;
|
||||
(void)obj;
|
||||
(void)unlock;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* template.c */
|
||||
CK_RV template_attribute_get_ulong(TEMPLATE *tmpl, CK_ATTRIBUTE_TYPE type,
|
||||
CK_ULONG *value)
|
||||
{
|
||||
(void)tmpl;
|
||||
(void)type;
|
||||
(void)value;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* attributes.c */
|
||||
CK_RV get_ulong_attribute_by_type(CK_ATTRIBUTE_PTR attrs,
|
||||
CK_ULONG attrs_len, CK_ULONG type,
|
||||
CK_ULONG *value)
|
||||
{
|
||||
(void)attrs;
|
||||
(void)attrs_len;
|
||||
(void)type;
|
||||
(void)value;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
CK_RV dup_attribute_array_no_alloc(CK_ATTRIBUTE_PTR orig, CK_ULONG num_attrs,
|
||||
CK_ATTRIBUTE_PTR dest)
|
||||
{
|
||||
(void)orig;
|
||||
(void)num_attrs;
|
||||
(void)dest;
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
/* p11util.c */
|
||||
CK_BBOOL is_attribute_attr_array(CK_ATTRIBUTE_TYPE type)
|
||||
{
|
||||
(void)type;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -2,13 +2,15 @@ check_PROGRAMS = testcases/unit/policytest testcases/unit/hashmaptest \
|
||||
testcases/unit/mechtabletest testcases/unit/configdump \
|
||||
testcases/unit/buffertest testcases/unit/uritest \
|
||||
testcases/unit/pintest testcases/unit/asn1test \
|
||||
testcases/unit/asn1fuzztest testcases/unit/objectflattentest
|
||||
testcases/unit/asn1fuzztest testcases/unit/objectflattentest \
|
||||
testcases/unit/padtest
|
||||
|
||||
TESTS = testcases/unit/policytest testcases/unit/hashmaptest \
|
||||
testcases/unit/mechtabletest testcases/unit/configdump \
|
||||
testcases/unit/buffertest testcases/unit/uritest \
|
||||
testcases/unit/pintest.sh testcases/unit/asn1test \
|
||||
testcases/unit/asn1fuzztest testcases/unit/objectflattentest
|
||||
testcases/unit/asn1fuzztest testcases/unit/objectflattentest \
|
||||
testcases/unit/padtest
|
||||
|
||||
EXTRA_DIST += testcases/unit/pintest.sh
|
||||
noinst_HEADERS += testcases/unit/unittest.h testcases/unit/asn1test_keys.h \
|
||||
@@ -119,3 +121,13 @@ testcases_unit_objectflattentest_CFLAGS=-I${top_srcdir}/usr/lib/common \
|
||||
-DSTDLL_NAME=\"objectflattentest\" -DOCK_UNIT_TESTS
|
||||
|
||||
testcases_unit_objectflattentest_LDFLAGS=-lpthread -lcrypto
|
||||
|
||||
testcases_unit_padtest_SOURCES=testcases/unit/padtest.c \
|
||||
testcases/unit/padtest_stubs.c usr/lib/common/utility.c \
|
||||
usr/lib/common/trace.c
|
||||
|
||||
testcases_unit_padtest_CFLAGS=-I${top_srcdir}/usr/lib/common \
|
||||
-I${top_srcdir}/usr/include -I${top_srcdir}/usr/lib/api \
|
||||
-DSTDLL_NAME=\"padtest\" -DTOK_NEW_DATA_STORE=0x0003000c
|
||||
|
||||
testcases_unit_padtest_LDFLAGS=-lpthread -lcrypto
|
||||
|
||||
Reference in New Issue
Block a user