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