LibItsSecurity_Functions.ttcn 229 KB
Newer Older
Yann Garcia's avatar
Yann Garcia committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
/**
 *  @Author   ETSI / STF481 / STF507 / STF517 / STF538 / STF545
 *  @version  $Url$
 *            $Id$
 *  @desc     Module containing functions for Security Protocol
 *  @copyright   ETSI Copyright Notification
 *               No part may be reproduced except as authorized by written permission.
 *               The copyright and the foregoing restriction extend to reproduction in all media.
 *               All rights reserved.
 *
 */
module LibItsSecurity_Functions {
    
    // Libcommon
    import from LibCommon_BasicTypesAndValues all;
    import from LibCommon_DataStrings all;

    // LibIts
    import from Ieee1609Dot2BaseTypes language "ASN.1:1997" all;
    import from Ieee1609Dot2 language "ASN.1:1997" all;
    import from EtsiTs103097Module language "ASN.1:1997" all;
    
    // LibItsCommon
    import from LibItsCommon_Functions all;
    //import from LibItsCommon_TypesAndValues all;
    import from LibItsCommon_Pixits all;
    
    // LibItsSecurity
    import from LibItsSecurity_TypesAndValues all;
    import from LibItsSecurity_Templates all;
    import from LibItsSecurity_Pixits all;
    import from LibItsSecurity_Pics all;
    import from LibItsSecurity_TestSystem all;
    
    group helpersFunctions {
        
        /**
         * @desc    Produces a 256-bit (32-byte) hash value
         * @param   p_toBeHashedData Data to be used to calculate the hash value
         * @return  The hash value
         */
        function f_hashWithSha256(
                                  in octetstring p_toBeHashedData
        ) return Oct32 {
            return fx_hashWithSha256(p_toBeHashedData);
        } // End of function f_hashWithSha256
        
        /**
         * @desc    Produces a 384-bit (48-byte) hash value
         * @param   p_toBeHashedData Data to be used to calculate the hash value
         * @return  The hash value
         */
        function f_hashWithSha384(
                                  in octetstring p_toBeHashedData
        ) return Oct48 {
            return fx_hashWithSha384(p_toBeHashedData);
        } // End of function f_hashWithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_privateKey                  The private key for signature
         * @return  The signature value
         */
        function f_signWithEcdsaNistp256WithSha256(
                                                   in octetstring p_toBeSignedSecuredMessage,
                                                   in Oct32 p_certificateIssuer,
                                                   in Oct32 p_privateKey
        ) return octetstring {
            log(">>> f_signWithEcdsaNistp256WithSha256: p_toBeSignedSecuredMessage= ", p_toBeSignedSecuredMessage);
            log(">>> f_signWithEcdsaNistp256WithSha256: p_certificateIssuer= ", p_certificateIssuer);
            log(">>> f_signWithEcdsaNistp256WithSha256: p_privateKey= ", p_privateKey);
            
            return fx_signWithEcdsaNistp256WithSha256(
                p_toBeSignedSecuredMessage,
                p_certificateIssuer,
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaNistp256WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_privateKey                  The private key for signature
         * @return  The signature value
         */
        function f_signWithEcdsaBrainpoolp256r1WithSha256(
                                                        in octetstring p_toBeSignedSecuredMessage,
                                                        in Oct32 p_certificateIssuer,
                                                        in Oct32 p_privateKey
        ) return octetstring {
            return fx_signWithEcdsaBrainpoolp256r1WithSha256(
                p_toBeSignedSecuredMessage,
                p_certificateIssuer,
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaBrainpoolp256r1WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2
         * @param   p_toBeSignedSecuredMessage    The data to be signed
         * @param   p_certificateIssuer           The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_privateKey                  The private key for signature
         * @return  The signature value
         */
        function f_signWithEcdsaBrainpoolp384r1WithSha384(
                                                        in octetstring p_toBeSignedSecuredMessage,
                                                        in Oct48 p_certificateIssuer,
                                                        in Oct48 p_privateKey
        ) return octetstring {
          log(">>> f_signWithEcdsaBrainpoolp384r1WithSha384: ", p_toBeSignedSecuredMessage);
          log(">>> f_signWithEcdsaBrainpoolp384r1WithSha384: ", p_certificateIssuer);
          log(">>> f_signWithEcdsaBrainpoolp384r1WithSha384: ", p_privateKey);
            return fx_signWithEcdsaBrainpoolp384r1WithSha384(
                p_toBeSignedSecuredMessage,
                p_certificateIssuer,
                p_privateKey
            );
            
        } // End of function f_signWithEcdsaBrainpoolp384r1WithSha384
        
        function f_decrypt(
                           in octetstring         p_encryptPrivateKey,
                           in EtsiTs103097Data    p_encrypedSecuredMessage,
                           in octetstring         p_salt,
                           out EtsiTs103097Data   p_decrypedSecuredMessage,
                           out octetstring        p_aes_sym_enc_key
        ) return boolean {
            if (ischosen(p_encrypedSecuredMessage.content.encryptedData)) {
                var PKRecipientInfo v_pKRecipientInfo;
                var RecipientInfo v_recipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0];
            var octetstring v_decryptedSecuredMessage;
                
              log(">>> f_decrypt: p_encryptPrivateKey=", p_encryptPrivateKey);
              log(">>> f_decrypt: p_encrypedSecuredMessage=", p_encrypedSecuredMessage);
              log(">>> f_decrypt: p_salt=", p_salt);
              
                // Check the private encryption key
                if (not(isbound(p_encryptPrivateKey))) {
                  log("*** " & testcasename() & ":ERROR: Failed to load encryption private key ***");
                  return false;
                }
                
                if (ischosen(v_recipientInfo.certRecipInfo)) {
                  v_pKRecipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0].certRecipInfo;
                  // Read the certificate based on the recipientId
                } else if (ischosen(v_recipientInfo.signedDataRecipInfo)) {
                v_pKRecipientInfo := p_encrypedSecuredMessage.content.encryptedData.recipients[0].signedDataRecipInfo;
                  // Read the certificate based on the recipientId
                } else {
                  log("*** " & testcasename() & ":ERROR: Unsupported RecipientInfo variant ***");
                  return false;
                }
                
              log("f_decrypt: v_pKRecipientInfo=", v_pKRecipientInfo);
            if (isbound(v_pKRecipientInfo)) {
                if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256)) {
                  var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext;
                  
                  log("f_decrypt: v_ciphertext=", v_ciphertext);
                  if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_0)) {
                      v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256(
                                                                                        v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                        p_encryptPrivateKey,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_0,
                                                                                        0,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.c,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.t,
                                                                                        v_ciphertext.aes128ccm.nonce,
                                                                                        p_salt,
                                                                                        p_aes_sym_enc_key
                                                                                        );
                  } else if (ischosen(v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_1)) {
                      v_decryptedSecuredMessage := f_decryptWithEciesNistp256WithSha256(
                                                                                        v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                        p_encryptPrivateKey,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.v.compressed_y_1,
                                                                                        1,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.c,
                                                                                        v_pKRecipientInfo.encKey.eciesNistP256.t,
                                                                                        v_ciphertext.aes128ccm.nonce,
                                                                                        p_salt,
                                                                                        p_aes_sym_enc_key
                                                                                        );
                  } else {
                    log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***");
                    return false;
                  }
                  if (isbound(v_decryptedSecuredMessage)) {
                    var bitstring v_decode := oct2bit(v_decryptedSecuredMessage);
                    if (decvalue(v_decode, p_decrypedSecuredMessage) == 0) {
                      return true;
                    } else {
                      log("*** " & testcasename() & ":ERROR: Faild to decode secured message ***");
                    }
                  }
                } else if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1)) {
                  var SymmetricCiphertext v_ciphertext := p_encrypedSecuredMessage.content.encryptedData.ciphertext;
                  if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_0)) {
                    v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256r1WithSha256(
                                                                                           v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                           p_encryptPrivateKey,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_0,
                                                                                           0,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t,
                                                                                           v_ciphertext.aes128ccm.nonce,
                                                                                           p_salt,                                                                                                                                                     p_aes_sym_enc_key
                                                                                      );
                  } else if (ischosen(v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_1)) {
                    v_decryptedSecuredMessage := f_decryptWithEciesBrainpoolp256r1WithSha256(
                                                                                           v_ciphertext.aes128ccm.ccmCiphertext,
                                                                                           p_encryptPrivateKey,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.v.compressed_y_1,
                                                                                           1,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.c,
                                                                                           v_pKRecipientInfo.encKey.eciesBrainpoolP256r1.t,
                                                                                           v_ciphertext.aes128ccm.nonce,
                                                                                           p_salt,
                                                                                           p_aes_sym_enc_key
                                                                                      );
                  } else {
                    log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***");
                    return false;
                  }
              } else {
                log("*** " & testcasename() & ":ERROR: Non canonical ephemeral encryption keys ***");
                return false;
              }
              // TODO else, other variants shall be processed here if
            } else {
              log("*** " & testcasename() & ":ERROR: Invalid recipient info ***");
              return false;
            }
                  if (isbound(v_decryptedSecuredMessage)) {
                    var bitstring v_decode := oct2bit(v_decryptedSecuredMessage);
                    if (decvalue(v_decode, p_decrypedSecuredMessage) == 0) {
                      return true;
                    } else {
                      log("*** " & testcasename() & ":ERROR: Faild to decode secured message ***");
                    }
                  }
            } else {
              log("*** " & testcasename() & ":ERROR: Message not encrypted ***");
            }
            
            return false;
        } // End of function f_decrypt

        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Nist-P256 algorithm
         * @param   p_toBeEncryptedSecuredMessage    The data to be encrypted
         * @param   p_recipientsPublicKeyCompressed  The Recipient's compressed public key
         * @param   p_compressed_mode                 The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         * @return  The encrypted message
         */
        function f_encryptWithEciesNistp256WithSha256(
                                                      in octetstring p_toBeEncryptedSecuredMessage,
                                                      in Oct32 p_recipientsPublicKeyCompressed,
                                                      in integer p_compressed_mode,
                                                      in octetstring p_salt,
                                                      out Oct32 p_publicEphemeralKeyCompressed,
                                                      out integer p_ephemeralKeyModeCompressed,
                                                      out Oct16 p_aes_sym_key,
                                                      out Oct16 p_encrypted_sym_key,
                                                      out Oct16 p_authentication_vector,
                                                      out Oct12 p_nonce
        ) return octetstring {
          return fx_encryptWithEciesNistp256WithSha256(
                                                       p_toBeEncryptedSecuredMessage,
                                                       p_recipientsPublicKeyCompressed,
                                                       p_compressed_mode,
                                                       p_salt,
                                                       p_publicEphemeralKeyCompressed,
                                                       p_ephemeralKeyModeCompressed,
                                                       p_aes_sym_key,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce
                                                       );
        } // End of function f_encryptWithEciesNistp256WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Nist-P256 algorithm
         * @param   p_encryptedSecuredMessage    The data to be decrypted
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @return  The decrypted message
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         */
        function f_decryptWithEciesNistp256WithSha256(
                                                      in octetstring p_encryptedSecuredMessage,
                                                      in Oct32 p_privateEncKey,
                                                      in Oct32 p_publicEphemeralKeyCompressed,
                                                      in integer p_ephemeralKeyModeCompressed,
                                                      in Oct16 p_encrypted_sym_key,
                                                      in Oct16 p_authentication_vector,
                                                      in Oct12 p_nonce,
                                                      in Oct32 p_salt,
                                                      out Oct16 p_aes_sym_enc_key
        ) return octetstring {
          return fx_decryptWithEciesNistp256WithSha256(
                                                       p_encryptedSecuredMessage,
                                                       p_privateEncKey,
                                                       p_publicEphemeralKeyCompressed, 
                                                       p_ephemeralKeyModeCompressed,
                                                       p_encrypted_sym_key,
                                                       p_authentication_vector,
                                                       p_nonce,
                                                       p_salt,
                                                       p_aes_sym_enc_key
                                                       );
        } // End of function f_decryptWithEcdsaNistp256WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) encryption using Brainpool-P256 algorithm
         * @param   p_toBeEncryptedSecuredMessage    The data to be encrypted
         * @param   p_recipientsPublicKeyCompressed  The Recipient's compressed public key
         * @param   p_compressed_mode                 The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @return  The encrypted message
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         */
        function f_encryptWithEciesBrainpoolp256r1WithSha256(
                                                           in octetstring p_toBeEncryptedSecuredMessage,
                                                           in Oct32 p_recipientsPublicKeyCompressed,
                                                           in integer p_compressed_mode,
                                                           in octetstring p_salt,
                                                           out Oct32 p_publicEphemeralKeyCompressed,
                                                           out integer p_ephemeralKeyModeCompressed,
                                                           out Oct16 p_aes_sym_key,
                                                           out Oct16 p_encrypted_sym_key,
                                                           out Oct16 p_authentication_vector,
                                                           out Oct12 p_nonce
        ) return octetstring {
          return fx_encryptWithEciesBrainpoolp256r1WithSha256(
                                                            p_toBeEncryptedSecuredMessage,
                                                            p_recipientsPublicKeyCompressed,
                                                            p_compressed_mode,
                                                            p_salt,
                                                            p_publicEphemeralKeyCompressed,
                                                            p_ephemeralKeyModeCompressed,
                                                            p_aes_sym_key,
                                                            p_encrypted_sym_key,
                                                            p_authentication_vector,
                                                            p_nonce
                                                            );
        } // End of function f_encryptWithEciesBrainpoolp256r1WithSha256
        
        /**
         * @desc    Produces a Elliptic Curve Digital Encrytion Algorithm (ECIES) decryption using Brainpool-P256 algorithm
         * @param   p_encryptedSecuredMessage    The data to be decrypted
         * @param   p_publicEphemeralKeyCompressed   The generated ephemeral compressed key
         * @param   p_ephemeralKeyModeCompressed     The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @param   p_encrypted_sym_key              The encrypted AES 128 CCM symmetric key
         * @param   p_authentication_vector          The tag of the AES 128 CCM symmetric key encryption
         * @param   p_nonce                          The nonce vector of the AES 128 CCM symmetric key encryption
         * @return  The decrypted message
         * @see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES
         * @see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/
         * @see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf
         */
        function f_decryptWithEciesBrainpoolp256r1WithSha256(
                                                           in octetstring p_encryptedSecuredMessage,
                                                           in Oct32 p_privateEncKey,
                                                           in Oct32 p_publicEphemeralKeyCompressed, 
                                                           in integer p_ephemeralKeyModeCompressed,
                                                           in Oct16 p_encrypted_sym_key,
                                                           in Oct16 p_authentication_vector,
                                                           in Oct12 p_nonce,
                                                           in Oct32 p_salt,
                                                           out Oct16 p_aes_sym_enc_key
        ) return octetstring {
          return fx_decryptWithEciesBrainpoolp256r1WithSha256(
                                                            p_encryptedSecuredMessage,
                                                            p_privateEncKey,
                                                            p_publicEphemeralKeyCompressed, 
                                                            p_ephemeralKeyModeCompressed,
                                                            p_encrypted_sym_key,
                                                            p_authentication_vector,
                                                            p_nonce,
                                                            p_salt,
                                                            p_aes_sym_enc_key
                                                            );
        } // End of function f_decryptWithEcdsaBrainpoolp256r1WithSha256
        
        /**
         * @desc Compute the HashedId8 value from the hash value
         * @param p_hash The hash value
         * @return The HashedId8 value
         * @verdict
         */
        function f_hashedId8FromSha256( 
                                       in Oct32 p_hash
        ) return HashedId8 {
            return substr(p_hash, lengthof(p_hash) - 8, 8);
        } // End of function f_hashedId8FromSha256
        
        /**
         * @desc Compute the HashedId8 value from the hash value
         * @param p_hash The hash value
         * @return The HashedId8 value
         * @verdict
         */
        function f_hashedId8FromSha384( 
                                       in Oct48 p_hash
        ) return HashedId8 {
            return substr(p_hash, lengthof(p_hash) - 8, 8);
        } // End of function f_hashedId8FromSha384
        
        /**
         * @desc Compute the HashedId3 value from the HashedId8 value
         * @param p_hashp_hashedId8 The HashedId8 value
         * @return The HashedId3 value
         * @verdict Unchanged
         */
        function f_hashedId3FromHashedId8(
                                          in HashedId8 p_hashedId8
        ) return HashedId3 {
            return substr(p_hashedId8, lengthof(p_hashedId8) - 3, 3);
        }  // End of function f_hashedId3FromHashedId8
        
        /**
         * @desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaNistp256PublicKeyCompressed   The compressed public key
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaNistp256WithSha256(
                                                     in octetstring p_toBeVerifiedData,
                                                     in Oct32 p_certificateIssuer,
                                                     in Oct64 p_signature,
                                                     in Oct32 p_ecdsaNistp256PublicKeyCompressed,
                                                     in integer p_compressed_mode
        ) return boolean {
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaNistp256WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyCompressed", p_ecdsaNistp256PublicKeyCompressed);
            return fx_verifyWithEcdsaNistp256WithSha256(
                                                        p_toBeVerifiedData,
                                                        p_certificateIssuer,
                                                        p_signature,
                                                        p_ecdsaNistp256PublicKeyCompressed,
                                                        p_compressed_mode
                                                        );
        } // End of function f_verifyWithEcdsaNistp256WithSha256
        
        /**
         * @desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaNistp256PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaNistp256PublicKeyY   The public key (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaNistp256WithSha256_1( // TODO To be removed
                                                       in octetstring p_toBeVerifiedData,
                                                       in Oct32 p_certificateIssuer,
                                                       in Oct64 p_signature,
                                                       in Oct32 p_ecdsaNistp256PublicKeyX,
                                                       in Oct32 p_ecdsaNistp256PublicKeyY
        ) return boolean {
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaNistp256WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaNistp256WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyX", p_ecdsaNistp256PublicKeyX);
//            log("f_verifyWithEcdsaNistp256WithSha256: ecdsaNistp256PublicKeyY", p_ecdsaNistp256PublicKeyY);
            return fx_verifyWithEcdsaNistp256WithSha256_1(
                p_toBeVerifiedData,
                p_certificateIssuer,
                p_signature,
                p_ecdsaNistp256PublicKeyX,
                p_ecdsaNistp256PublicKeyY);
        } // End of function f_verifyWithEcdsaNistp256WithSha256_1
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp256PublicKeyCompressed   The compressed public key
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp256r1WithSha256(
                                                          in octetstring p_toBeVerifiedData,
                                                          in Oct32 p_certificateIssuer,
                                                          in Oct64 p_signature,
                                                          in Oct32 p_ecdsaBrainpoolp256PublicKeyCompressed,
                                                          in integer p_compressed_mode
        ) return boolean {
            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: toBeVerifiedData", p_toBeVerifiedData);
            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: signature", p_signature);
            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: ecdsaBrainpoolp256PublicKeyCompressed", p_ecdsaBrainpoolp256PublicKeyCompressed);
            return fx_verifyWithEcdsaBrainpoolp256r1WithSha256(
                                                             p_toBeVerifiedData,
                                                             p_certificateIssuer,
                                                             p_signature,
                                                             p_ecdsaBrainpoolp256PublicKeyCompressed,
                                                             p_compressed_mode
                                                             );
        } // End of function f_verifyWithEcdsaBrainpoolp256r1WithSha256
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp256PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaBrainpoolp256PublicKeyY   The public key (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp256r1WithSha256_1( // TODO To be removed
                                                            in octetstring p_toBeVerifiedData,
                                                            in Oct32 p_certificateIssuer,
                                                            in Oct64 p_signature,
                                                            in Oct32 p_ecdsaBrainpoolp256PublicKeyX,
                                                            in Oct32 p_ecdsaBrainpoolp256PublicKeyY
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: ecdsaBrainpoolp256PublicKeyX", p_ecdsaBrainpoolp256PublicKeyX);
//            log("f_verifyWithEcdsaBrainpoolp256r1WithSha256: ecdsaBrainpoolp256PublicKeyY", p_ecdsaBrainpoolp256PublicKeyY);
            return fx_verifyWithEcdsaBrainpoolp256r1WithSha256_1(
                p_toBeVerifiedData,
                p_certificateIssuer,
                p_signature,
                p_ecdsaBrainpoolp256PublicKeyX,
                p_ecdsaBrainpoolp256PublicKeyY);
        } // End of function f_verifyWithEcdsaBrainpoolp256r1WithSha256_1
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp384PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaBrainpoolp384PublicKeyY   The public key (y coordinate)
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp384r1WithSha384(
                                                          in octetstring p_toBeVerifiedData,
                                                          in Oct48 p_certificateIssuer,
                                                          in Oct96 p_signature,
                                                          in Oct48 p_ecdsaBrainpoolp384PublicKeyCompressed,
                                                          in integer p_compressed_mode
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: ecdsaBrainpoolp384PublicKeyCompressed", p_ecdsaBrainpoolp384PublicKeyCompressed);
            return fx_verifyWithEcdsaBrainpoolp384r1WithSha384(
                                                             p_toBeVerifiedData,
                                                             p_certificateIssuer,
                                                             p_signature,
                                                             p_ecdsaBrainpoolp384PublicKeyCompressed,
                                                             p_compressed_mode
                                                             );
        } // End of function f_verifyWithEcdsaBrainpoolp384r1WithSha384
        
        /**
         * @Desc    Verify the signature of the specified data
         * @param   p_toBeVerifiedData          The data to be verified
         * @param   p_certificateIssuer         The whole-hash issuer certificate or int2oct(0, 32) in case of self signed certificate
         * @param   p_signature                 The signature
         * @param   p_ecdsaBrainpoolp384PublicKeyX   The public key (x coordinate)
         * @param   p_ecdsaBrainpoolp384PublicKeyY   The public key (y coordinate)
         * @return  true on success, false otherwise
         */
        function f_verifyWithEcdsaBrainpoolp384r1WithSha384_1( // TODO To be removed
                                                            in octetstring p_toBeVerifiedData,
                                                            in Oct48 p_certificateIssuer,
                                                            in Oct96 p_signature,
                                                            in Oct48 p_ecdsaBrainpoolp384PublicKeyX,
                                                            in Oct48 p_ecdsaBrainpoolp384PublicKeyY
        ) return boolean {
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: toBeVerifiedData", p_toBeVerifiedData);
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: toBeVerifiedData length", lengthof(p_toBeVerifiedData));
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: signature", p_signature);
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: ecdsaBrainpoolp384PublicKeyX", p_ecdsaBrainpoolp384PublicKeyX);
//            log("f_verifyWithEcdsaBrainpoolp384r1WithSha384: ecdsaBrainpoolp384PublicKeyY", p_ecdsaBrainpoolp384PublicKeyY);
            return fx_verifyWithEcdsaBrainpoolp384r1WithSha384_1(
                p_toBeVerifiedData,
                p_certificateIssuer,
                p_signature,
                p_ecdsaBrainpoolp384PublicKeyX,
                p_ecdsaBrainpoolp384PublicKeyY);
        } // End of function f_verifyWithEcdsaBrainpoolp384r1WithSha384_1
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @param   p_publicKeyCompressed The compressed public keys
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_nistp256(
                                              out Oct32 p_privateKey,
                                              out Oct32 p_publicKeyX,
                                              out Oct32 p_publicKeyY,
                                              out Oct32 p_publicKeyCompressed,
                                              out integer p_compressed_mode
                                             ) return boolean {
          log(">>> f_generate_key_pair_nistp256");
          return fx_generateKeyPair_nistp256(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode);
        }
        
        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @param   p_publicKeyCompressed The compressed public keys
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_brainpoolp256r1(
                                                     out Oct32 p_privateKey,
                                                     out Oct32 p_publicKeyX,
                                                     out Oct32 p_publicKeyY,
                                                     out Oct32 p_publicKeyCompressed,
                                                     out integer p_compressed_mode
                                                     ) return boolean {
          log(">>> f_generate_key_pair_brainpoolp256r1");
          return fx_generateKeyPair_brainpoolp256r1(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode);
        }

        /**
         * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
         *          This function should not be used by the ATS
         * @param   p_privateKey    The new private key value
         * @param   p_publicKeyX    The new public key value (x coordinate)
         * @param   p_publicKeyX    The new public key value (y coordinate)
         * @param   p_publicKeyCompressed The compressed public keys
         * @param   p_compressed_mode The compressed mode, 0 if the latest bit of Y-coordinate is 0, 1 otherwise
         * @return  true on success, false otherwise
         */
        function f_generate_key_pair_brainpoolp384r1(
                                                     out Oct48 p_privateKey,
                                                     out Oct48 p_publicKeyX,
                                                     out Oct48 p_publicKeyY,
                                                     out Oct48 p_publicKeyCompressed,
                                                     out integer p_compressed_mode
                                                     ) return boolean {
          return fx_generateKeyPair_brainpoolp384r1(p_privateKey, p_publicKeyX, p_publicKeyY, p_publicKeyCompressed, p_compressed_mode);
        }

        /**
        * @desc    Calculate digest over the certificate
        * @param   p_cert The certificate
        * @return  the HashedId8 value
        * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13   HashedId8
        */
        function f_calculateDigestFromCertificate(
                                                  in Certificate p_cert
        ) return HashedId8 {
            var octetstring v_hash;
            
            if (PICS_SEC_SHA256) {
                v_hash := f_calculateDigestSha256FromCertificate(p_cert);
            } if (PICS_SEC_SHA384) {
                v_hash := f_calculateDigestSha384FromCertificate(p_cert);
            } 
            
            return substr(v_hash, lengthof(v_hash) - 8, 8);
        } // End of function f_calculateDigestFromCertificate
        
        /**
        * @desc    Calculate digest over the certificate
        * @param   p_cert The certificate
        * @return  the HashedId8 value
        * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13   HashedId8
        */
        function f_calculateDigestSha256FromCertificate(
                                                        in EtsiTs103097Certificate p_cert
        ) return HashedId8 {
            var octetstring v_toBeHashedData;
            var octetstring v_hash;
                        
            v_toBeHashedData := bit2oct(encvalue(p_cert));
            v_hash := f_hashWithSha256(v_toBeHashedData);
            return substr(v_hash, lengthof(v_hash) - 8, 8);
        } // End of function f_calculateDigestSha256FromCertificate
        
        function f_calculateDigestSha384FromCertificate(
                                                        in EtsiTs103097Certificate p_cert
        ) return HashedId8 {
            var octetstring v_toBeHashedData;
            var octetstring v_hash;
                        
            v_toBeHashedData := bit2oct(encvalue(p_cert));
            v_hash := f_hashWithSha384(v_toBeHashedData);
            return substr(v_hash, lengthof(v_hash) - 8, 8);
        } // End of function f_calculateDigestSha384FromCertificate
        
        function f_duration2time(
                                 in Duration p_duration
        ) return UInt16 {
            if (ischosen(p_duration.seconds)) {
                return p_duration.seconds;
            } else if (ischosen(p_duration.minutes)) { 
                return p_duration.minutes;
            } else if (ischosen(p_duration.hours)) { 
                return p_duration.hours;
            } else if (ischosen(p_duration.sixtyHours)) {
                return p_duration.sixtyHours;
            } else if (ischosen(p_duration.years)) {
                return p_duration.years;
            }
            
            return 0; // Unrechable code
        } // End of function f_duration2time
        
        group hostSignatureHelpers {
            
            /**
            * @desc    Initialize [out] certificates according to the specified certificate name
            * @param   p_certificateName The certificate name to be used
            * @param   p_aaCertificate The AA certificate [out]
            * @param   p_atCertificate The AT certificate [out]
            * @return  true on succes, false otherwise
            * @see Draft ETSI TS 103 097 V1.1.14 Clause 4.2.13   HashedId8
            */
            function f_prepareCertificates(
                                           in template (omit) charstring p_certificateName,
                                           out EtsiTs103097Certificate p_aaCertificate,
                                           out EtsiTs103097Certificate p_atCertificate
            ) runs on ItsSecurityBaseComponent return boolean {
                //log(">>> f_prepareCertificates: ", p_certificateName);
                
                // Load certificates if required
                if ((lengthof(p_certificateName) > 0) and (valueof(p_certificateName) != cc_taCert_A)) {
                    var HashedId8 v_digest;
                    var charstring v_cert;
                    
                    if (f_readCertificate(valueof(p_certificateName), p_atCertificate) == false){
                        log("f_prepareCertificates: Failed to read certificate ", p_certificateName);
                        return false;
                    }
                    if (ischosen(p_atCertificate.issuer.sha256AndDigest)) {
                        v_digest := p_atCertificate.issuer.sha256AndDigest;
                    } else if (ischosen(p_atCertificate.issuer.sha384AndDigest)) {
                        v_digest := p_atCertificate.issuer.sha384AndDigest;
                    } else {
                        log("f_prepareCertificates: Invalid certificate issuer ", p_atCertificate.issuer);
                        return false;
                    }
                    if (f_getCertificateFromDigest(v_digest, p_aaCertificate, v_cert) == false) {
                        log("f_prepareCertificates: Failed to read certificate issuer ", v_digest);
                        return false;
                    }
                } else {
                    p_atCertificate := vc_atCertificate;
                    p_aaCertificate := vc_aaCertificate;
                }
                // Store the certificate to build this message
                vc_lastAtCertificateUsed := p_atCertificate;
                
                return true;
            } // End of function f_prepareCertificates
            
            /**
             * @desc  This function build and sign the SecureMessage part covered by the signature process
             * @param p_securedMessage      The signed  SecureMessage part
             * @param p_payloadField       Payloads to be included in the message
             * @param p_mandatoryHeaders    Mandatory headers for the selected profile 
             * @param p_headerInfo        HeaderInfo to be inserted in the message
             * @param p_securityProfile     Selected security profile
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredMessage(
                                             inout EtsiTs103097Data p_securedMessage,
                                             in charstring p_certificateName,
                                             in ToBeSignedData p_payloadField
            ) runs on ItsSecurityBaseComponent return boolean {
                
                // Local variables
                var octetstring v_secPayload, v_signature;
                var ToBeSignedData v_toBeSignedData;
                var octetstring v_certificateIssuer;
                var octetstring v_privateKey;

                log(">>> f_buildGnSecuredMessage: p_securedMessage=", p_securedMessage);
                log(">>> f_buildGnSecuredMessage: p_payloadField=", p_payloadField);
                
                // Prepare payload to be signed
                v_toBeSignedData := valueof(p_payloadField);
                v_secPayload := bit2oct(encvalue(v_toBeSignedData));
                log("f_buildGnSecuredMessage: v_secPayload=", v_secPayload);
                
                // Signed payload
                if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) {
                    if(not f_readSigningKey(valueof(p_certificateName), v_privateKey)){
                        return false;
                    }
                } else {
                    if(not f_readSigningKey(cc_taCert_A, v_privateKey)){
                        return false;
                    }
                }
//                log("f_buildGnSecuredMessage: v_privateKey=", v_privateKey);
                f_getCertificateHash(p_certificateName, v_certificateIssuer);

                if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaNistP256Signature)) {
                  v_signature := f_signWithEcdsaNistp256WithSha256(
                                                                   v_secPayload,
                                                                   v_certificateIssuer,
                                                                   v_privateKey 
                                                                   );
                  p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaNistP256(
                                                                                                      m_ecdsaP256Signature(
                                                                                                                           m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                           substr(v_signature, 32, 32)
                                                                                                                           )
                                                                                                      ));
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP256r1Signature)) {
                    v_signature := f_signWithEcdsaBrainpoolp256r1WithSha256(
                                                                          v_secPayload,
                                                                          v_certificateIssuer, 
                                                                          v_privateKey 
                                                                          );
                    p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP256r1(
                                                                                                               m_ecdsaP256Signature(
                                                                                                                                    m_eccP256CurvePoint_x_only(substr(v_signature, 0, 32)),
                                                                                                                                    substr(v_signature, 32, 32)
                                                                                                                                    )
                                                                                                               ));
                } else if (ischosen(p_securedMessage.content.signedData.signature_.ecdsaBrainpoolP384r1Signature)) {
                  v_signature := f_signWithEcdsaBrainpoolp384r1WithSha384(
                                                                        v_secPayload,
                                                                        v_certificateIssuer, 
                                                                        v_privateKey 
                                                                        );
                  p_securedMessage.content.signedData.signature_ := valueof(m_signature_ecdsaBrainpoolP384r1(
                                                                                                             m_ecdsaP384Signature(
                                                                                                                                  m_eccP384CurvePoint_x_only(substr(v_signature, 0, 48)),
                                                                                                                                  substr(v_signature, 48, 48)
                                                                                                                                  )
                                                                                                             ));
                } // TODO To be continued
                
//                log("<<< f_buildGnSecuredMessage: p_securedMessage=", p_securedMessage);
                return true;
            } // End of function f_buildGnSecuredMessage
            
            /**
             * @desc  This function build and sign the SecureMessage part covered by the signature process including wrong elements of protocols. It is used for BO test cases
             * @param p_securedMessage      The signed  SecureMessage part
             * @param p_certificateName     The certificate name
             * @param  p_protocolVersion    The protocol version to be set. Default: 2
             * @param  p_trailerStatus      The Traile behaviour:
             *                              <li>0 for no trailer</li>
             *                              <li>1 for invalid trailer</li>
             *                              <li>2 for duplicated trailer</li>
             * @param p_payloadField        Payloads to be included in the message
             * @param p_mandatoryHeaders    Mandatory headers for the selected profile 
             * @param p_headerInfo        HeaderInfo to be inserted in the message
             * @param p_securityProfile     Selected security profile
             * @return true on success, false otherwise
             */
            function f_buildGnSecuredMessage_Bo(
                                                inout EtsiTs103097Data p_securedMessage,
                                                in template (value) charstring p_certificateName,
                                                in UInt8 p_protocolVersion := c_protocol_version,
                                                in integer p_trailerStatus := 0,
                                                in template (value) ToBeSignedData p_payloadField,
                                                in template (value) HeaderInfo p_mandatoryHeaders,
                                                in template (omit) HeaderInfo p_headerInfo := omit
            ) return boolean {
                
                // Local variables
                var octetstring v_secPayload, v_signature;
                var template (value) ToBeSignedData v_toBeSignedData;
                var integer i, j, k, n;
                var HeaderInfo v_headerFields;
                var Ieee1609Dot2Content v_toBeSignedPayload;
                var Oct32 v_privateKey;
                var UInt8 v_trailerSize;
                
                // Prepare headers
                if (not(ispresent(p_headerInfo))) {
                    v_headerFields := valueof(p_mandatoryHeaders);
                } else {/* FIXME To be reviewed 
                    // Merge p_headerInfo and v_mandatoryHeaders into v_headerFields
                        
                    i := 0; // index for p_headerInfo
                    j := 0; // index for v_mandatoryHeaders
                    k := 0; // index for v_headerFields
                        
                    // Special processing for signer_info
                    if (lengthof(valueof(p_headerInfo)) > 0 and valueof(p_headerInfo[i].type_) == e_signer_info) {
                        v_headerFields[k] := valueof(p_headerInfo[i]);
                        k := k + 1;
                        i := i + 1;
                    }
                    
                    for (j := j; j < lengthof(p_mandatoryHeaders); j := j + 1) {
                        // Search for mandatory header in p_HeaderFields
                        for (n := 0; n < lengthof(p_headerInfo); n := n + 1) {
                            if (valueof(p_headerInfo[n].type_) == valueof(p_mandatoryHeaders[j].type_)) {
                                // mandatory header already in p_HeaderFields
                                break;
                            }
                        } // End of 'for' statement
                        if (n >= lengthof(p_headerInfo)) {
                            if (valueof(p_mandatoryHeaders[j].type_) != e_signer_info) {
                                // Add headers from p_headerInfo having lower number than mandatory header
                                for (n := i; n < lengthof(p_headerInfo) and valueof(p_headerInfo[n].type_) < valueof(p_mandatoryHeaders[j].type_); n := n + 1) {
                                    v_headerFields[k] := valueof(p_headerInfo[n]);
                                    k := k + 1;
                                    i := i + 1;
                                }
                            }
                            // Add mandatory header
                            v_headerFields[k] := valueof(p_mandatoryHeaders[j]);
                            k := k + 1;
                        }
                    } // End of 'for' statement
                        
                    // Add remaining headers from p_HeaderFields
                    for ( i := i; i < lengthof(p_headerInfo); i := i + 1) {
                        // Add headers from p_headerInfo having lower number than mandatory header
                        v_headerFields[k] := valueof(p_headerInfo[i]);
                        k := k + 1;
                    } // End of 'for' statement
                */}
                
                // Prepare payload to be signed
                /* FIXME To be reviewed v_toBeSignedPayload := valueof(p_payloadField);
//                log("p_trailerStatus=", p_trailerStatus);
                if (p_trailerStatus == 0) {
                    v_trailerSize := 0;
                } else if (p_trailerStatus == 1) {
                    v_trailerSize := 67;
                } else if (p_trailerStatus == 2) {
                    v_trailerSize := 2 * 67;
                } else {
                    v_trailerSize := 67;
                }
                v_toBeSignedData := m_toBeSignedSecuredMessage_wrong_protocol(
                    v_headerFields,
                    v_toBeSignedPayload,
                    e_signature,
                    p_protocolVersion,
                    v_trailerSize
                );*/
//                log("m_toBeSignedSecuredMessage_wrong_protocol=", v_toBeSignedData);
                
                /* FIXME To be reviewedv_secPayload := bit2oct(encvalue(v_toBeSignedData));
//                log("v_secPayload=", v_secPayload);
                
                // Signed payload
                if (ispresent(p_certificateName) and (valueof(p_certificateName) != cc_taCert_A)) {
                    if(not f_readSigningKey(valueof(p_certificateName), v_privateKey)){
                        return false;
                    }
                } else {
                    if(not f_readSigningKey(cc_taCert_A, v_privateKey)){
                        return false;
                    }
                }
                v_signature := f_signWithEcdsaNistp256WithSha256(
                    v_secPayload, 
                    v_privateKey 
                );*/