@@ -800,6 +800,86 @@ static int openpgp_sign_or_auth(const CAPDU *capdu, RAPDU *rapdu, bool is_sign)
800
800
return 0 ;
801
801
}
802
802
803
+ // Parse and validate the specific TLV structure for ECC key
804
+ static int parse_ecc_key_tlv (const uint8_t * data , size_t data_len , key_type_t key_type , int * public_key_offset ) {
805
+ const uint8_t * p = data ;
806
+ size_t remaining = data_len ;
807
+ int fail ;
808
+ size_t length_size ;
809
+ uint16_t length ;
810
+
811
+ // 1. Check Cipher DO (A6)
812
+ if (remaining < 1 || * p != 0xA6 ) {
813
+ DBG_MSG ("Invalid Cipher DO tag\n" );
814
+ return -1 ;
815
+ }
816
+ p ++ ;
817
+ remaining -- ;
818
+
819
+ // Get Cipher DO length
820
+ length = tlv_get_length_safe (p , remaining , & fail , & length_size );
821
+ if (fail || length > remaining - length_size ) {
822
+ DBG_MSG ("Invalid Cipher DO length\n" );
823
+ return -1 ;
824
+ }
825
+ p += length_size ;
826
+ remaining -= length_size ;
827
+
828
+ // 2. Check Public Key DO (7F49)
829
+ if (remaining < 2 || * p != 0x7F || * (p + 1 ) != 0x49 ) {
830
+ DBG_MSG ("Invalid Public Key DO\n" );
831
+ return -1 ;
832
+ }
833
+ p += 2 ; // Skip 7F49 tag
834
+ remaining -= 2 ;
835
+
836
+ // Get Public Key DO length
837
+ length = tlv_get_length_safe (p , remaining , & fail , & length_size );
838
+ if (fail || length > remaining - length_size ) {
839
+ DBG_MSG ("Invalid Public Key DO length\n" );
840
+ return -1 ;
841
+ }
842
+ p += length_size ;
843
+ remaining -= length_size ;
844
+
845
+ // 3. Check External Public Key (86)
846
+ if (remaining < 1 || * p != 0x86 ) {
847
+ DBG_MSG ("Invalid External Public Key\n" );
848
+ return -1 ;
849
+ }
850
+ p ++ ;
851
+ remaining -- ;
852
+
853
+ // Get External Public Key length
854
+ length = tlv_get_length_safe (p , remaining , & fail , & length_size );
855
+ if (fail || length > remaining - length_size ) {
856
+ DBG_MSG ("Invalid External Public Key length\n" );
857
+ return -1 ;
858
+ }
859
+ p += length_size ;
860
+ remaining -= length_size ;
861
+
862
+ // 4. Validate key data based on key type
863
+ uint16_t expected_pubkey_len = PUBLIC_KEY_LENGTH [key_type ];
864
+
865
+ // For Short Weierstrass curves (SECP*, BP*), we need the 0x04 prefix
866
+ if (IS_SHORT_WEIERSTRASS (key_type )) {
867
+ if (length != expected_pubkey_len + 1 || * p != 0x04 ) {
868
+ DBG_MSG ("Invalid public key format for Short Weierstrass curve\n" );
869
+ return -1 ;
870
+ }
871
+ * public_key_offset = (p - data ) + 1 ; // Skip 0x04 prefix
872
+ } else { // For X25519
873
+ if (length != expected_pubkey_len ) {
874
+ DBG_MSG ("Invalid public key length for X25519\n" );
875
+ return -1 ;
876
+ }
877
+ * public_key_offset = p - data ;
878
+ }
879
+
880
+ return 0 ;
881
+ }
882
+
803
883
static int openpgp_decipher (const CAPDU * capdu , RAPDU * rapdu ) {
804
884
#ifndef FUZZ
805
885
if (PW1_MODE82 () == 0 ) EXCEPT (SW_SECURITY_STATUS_NOT_SATISFIED );
@@ -861,43 +941,11 @@ static int openpgp_decipher(const CAPDU *capdu, RAPDU *rapdu) {
861
941
862
942
int public_key_offset ;
863
943
864
- if (key .meta .type == SECP521R1 ) {
865
- if (DATA [0 ] != 0xA6 ||
866
- DATA [1 ] != 0x81 || DATA [2 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 8 ||
867
- DATA [3 ] != 0x7F || DATA [4 ] != 0x49 ||
868
- DATA [5 ] != 0x81 || DATA [6 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 4 ||
869
- DATA [7 ] != 0x86 ||
870
- DATA [8 ] != 0x81 || DATA [9 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 1 ||
871
- DATA [10 ] != 0x04 ) {
872
- DBG_MSG ("Incorrect data\n" );
873
- memzero (& key , sizeof (key ));
874
- EXCEPT (SW_WRONG_DATA );
875
- }
876
- public_key_offset = 11 ;
877
- } else {
878
- if (DATA [0 ] != 0xA6 || DATA [2 ] != 0x7F || DATA [3 ] != 0x49 || DATA [5 ] != 0x86 ) {
879
- DBG_MSG ("Incorrect data\n" );
880
- memzero (& key , sizeof (key ));
881
- EXCEPT (SW_WRONG_DATA );
882
- }
883
-
884
- if (IS_SHORT_WEIERSTRASS (key .meta .type )) {
885
- if (DATA [1 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 6 || DATA [4 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 3 ||
886
- DATA [6 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 1 || DATA [7 ] != 0x04 ) {
887
- DBG_MSG ("Incorrect length data\n" );
888
- memzero (& key , sizeof (key ));
889
- EXCEPT (SW_WRONG_DATA );
890
- }
891
- public_key_offset = 8 ;
892
- } else {
893
- if (DATA [1 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 5 || DATA [4 ] != PUBLIC_KEY_LENGTH [key .meta .type ] + 2 ||
894
- DATA [6 ] != PUBLIC_KEY_LENGTH [key .meta .type ]) {
895
- DBG_MSG ("Incorrect length data\n" );
896
- memzero (& key , sizeof (key ));
897
- EXCEPT (SW_WRONG_DATA );
898
- }
899
- public_key_offset = 7 ;
900
- }
944
+ // Use our new TLV parsing function to process the data
945
+ if (parse_ecc_key_tlv (DATA , LC , key .meta .type , & public_key_offset ) < 0 ) {
946
+ DBG_MSG ("Incorrect TLV data structure\n" );
947
+ memzero (& key , sizeof (key ));
948
+ EXCEPT (SW_WRONG_DATA );
901
949
}
902
950
903
951
if (ecdh (key .meta .type , key .ecc .pri , DATA + public_key_offset , RDATA ) < 0 ) {
0 commit comments