From 3527f97c284fda6b42dc636be57fb5a2beae4cb4 Mon Sep 17 00:00:00 2001 From: Leon Lynch Date: Sat, 28 Oct 2023 18:11:28 +0200 Subject: [PATCH] Remove optional block PB when adding new optional blocks Let tr31_opt_block_alloc() remove all instances of optional block PB when adding a new optional block. ANSI X9.143:2021, 6.3.6, states that the padding block will always be the last optional block in the header. Therefore, if optional block PB was previously added for whatever reason, for example via an export header by tr31-tool, it should be removed before adding further optional blocks. However, if no further optional blocks are added, an existing optional block PB is intentionally preserved specifically to allow the caller, or tr31-tool using an export header, to specify exact content for optional block PB. --- src/CMakeLists.txt | 12 +++++++++++- src/tr31.c | 26 ++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 844e2f8..b31abf8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -671,11 +671,21 @@ if(TARGET tr31-tool AND BUILD_TESTING) PASS_REGULAR_EXPRESSION "D1840S0ES00N0400CT000405D6020002F0MIICLjCCAdSgAwIBAgIIGDrdWBxuNpAwCgYIKoZIzj0EAwIwMTEXMBUGA1UECgwOQWxwaGEgTWVyY2hhbnQxFjAUBgNVBAMMDVNhbXBsZSBFQ0MgQ0EwHhcNMjAwODE1MDIxMDEwWhcNMjEwODE1MDIxMDEwWjBPMRcwFQYDVQQKDA5BbHBoYSBNZXJjaGFudDEfMB0GA1UECwwWVExTIENsaWVudCBDZXJ0aWZpY2F0ZTETMBEGA1UEAwwKMTIzNDU2Nzg5MDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEI/SLrH6fITA9y6Y3BneuoT/5\\+EHSepZxCYeSstGll2sVvmSDZWWSbN6lh5Fb/zagrDjjQ/gZtWIOTf2wL1vSGjgbcwgbQwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFHuvP526vFMywEoVoXZ5aXNfhnfeMB8GA1UdIwQYMBaAFI\\+ZFhOWF\\+oMtcfYwg15vH5WmWccMEIGA1UdHwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwuYWxwaGEtbWVyY2hhbnQuZXhhbXBsZS9TYW1wbGVFQ0NDQS5jcmwwCgYIKoZIzj0EAwIDSAAwRQIhAPuWWvCTmOdvQzUjCUmTX7H4sX4Ebpw\\+CI\\+aOQLu1DqwAiA0eR4FdMtvXV4P6\\+WMz5B10oea5xtLTfSgoBDoTkvKYQ==0002C4MIICDjCCAbOgAwIBAgIIfnOsCbsxHjwwCgYIKoZIzj0EAwIwNjEXMBUGA1UECgwOQWxwaGEgTWVyY2hhbnQxGzAZBgNVBAMMElNhbXBsZSBSb290IEVDQyBDQTAeFw0yMDA4MTUwMjEwMDlaFw0zMDA4MTMwMjEwMDlaMDExFzAVBgNVBAoMDkFscGhhIE1lcmNoYW50MRYwFAYDVQQDDA1TYW1wbGUgRUNDIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHCanM9n\\+Rji\\+3EROj\\+HlogmXMU1Fk1td7N3I/8rfFnre1GwWCUqXSePHxwQ9DRHCV3oht3OUU2kDfitfUIujA6OBrzCBrDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUj5kWE5YX6gy1x9jCDXm8flaZZxwwHwYDVR0jBBgwFoAUvElIifFlt6oeUaopV9Y0lJtyPVQwRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2NybC5hbHBoYS1tZXJjaGFudC5leGFtcGxlL1NhbXBsZVJvb3RFQ0NDQS5jcmwwCgYIKoZIzj0EAwIDSQAwRgIhALT8\\+DG\\+\\+\\+KuqqUGyBQ4YG4s34fqbujclxZTHxYWVVSNAiEAn3v5Xmct7fkLpkjGexiHsy6D90r0K2LlUqpN/069y5s=010004asdfKP10012331550BC9TS1320200818004100ZPB07" ) + # test export header containing optional blocks and padding, but not adding additional optional blocks add_test(NAME tr31_tool_test40 COMMAND tr31-tool --kbpk 88E1AB2A2E3DD38C1FA039A536500CC8A87AB9D62DC92C01058FA79F44657DE6 --export 3F419E1CB7079442AA37474C2EFBF8B8 --export-header D1234M7HG00N0200HM0621PB0A5V5E8F ) set_tests_properties(tr31_tool_test40 PROPERTIES - PASS_REGULAR_EXPRESSION "^D0128M7HG00N0200HM0621PB0A5V5E8F" + PASS_REGULAR_EXPRESSION "^D0128M7HG00N0200HM0621PB0A5V5E8F" # note that optional block padding content is intentionally preserved + ) + + # test export header containing optional blocks and padding and also adding additional optional blocks + add_test(NAME tr31_tool_test41 + COMMAND tr31-tool --kbpk 88E1AB2A2E3DD38C1FA039A536500CC8A87AB9D62DC92C01058FA79F44657DE6 --export 3F419E1CB7079442AA37474C2EFBF8B8 --export-header D1234M7HG00N0200HM0621PB0A5V5E8F --export-opt-block-LB "MyKey" + ) + set_tests_properties(tr31_tool_test41 + PROPERTIES + PASS_REGULAR_EXPRESSION "^D0144M7HG00N0300HM0621LB09MyKeyPB11" ) endif() diff --git a/src/tr31.c b/src/tr31.c index 9f7580b..4ebde5d 100644 --- a/src/tr31.c +++ b/src/tr31.c @@ -679,18 +679,44 @@ static struct tr31_opt_ctx_t* tr31_opt_block_alloc( ) { struct tr31_opt_ctx_t* opt_ctx; + bool opt_blk_pb_found = false; if (!ctx) { return NULL; } // repeated optional block IDs are not allowed + // and optional block PB must always be last // see ANSI X9.143:2021, 6.3.6 for (size_t i = 0; i < ctx->opt_blocks_count; ++i) { if (ctx->opt_blocks[i].id == id) { // existing optional block found return NULL; } + + if (ctx->opt_blocks[i].id == TR31_OPT_BLOCK_PB) { + // optional block PB found + opt_blk_pb_found = true; + } + } + + // if optional block PB already exists, remove all instances + // NOTE: it will be recreated by tr31_export() + // NOTE: if no new optional blocks are added, PB is intentionally preserved + if (opt_blk_pb_found) { + for (size_t i = 0; i < ctx->opt_blocks_count; ++i) { + if (ctx->opt_blocks[i].id == TR31_OPT_BLOCK_PB) { + free(ctx->opt_blocks[i].data); + ctx->opt_blocks[i].data = NULL; + + ctx->opt_blocks_count -= 1; + if (i < ctx->opt_blocks_count) { + size_t remaining_count = ctx->opt_blocks_count - i; + size_t remaining_bytes = sizeof(*ctx->opt_blocks) * remaining_count; + memmove(&ctx->opt_blocks[i], &ctx->opt_blocks[i + 1], remaining_bytes); + } + } + } } // grow optional block array