44from pyeudiw .trust .handler .interface import TrustHandlerInterface
55from pyeudiw .trust .model .trust_source import TrustSourceData , TrustEvaluationType
66from pyeudiw .trust .handler .exceptions import InvalidTrustHandlerConfiguration
7- from pyeudiw .jwk .parse import parse_pem , parse_x5c_keys , parse_certificate
7+ from pyeudiw .jwk .parse import parse_x5c_keys , parse_certificate
88from cryptojwt .jwk .jwk import key_from_jwk_dict
99from pyeudiw .x509 .verify import (
1010 PEM_cert_to_B64DER_cert ,
1111 to_DER_cert ,
1212 verify_x509_attestation_chain ,
1313 get_expiry_date_from_x5c ,
14- der_list_to_pem_list ,
15- pem_list_to_der_list ,
14+ to_pem_list ,
15+ to_der_list ,
1616 get_x509_info ,
1717 get_trust_anchor_from_x5c ,
1818 get_certificate_type
@@ -94,7 +94,7 @@ def __init__(
9494 logger .error (f"Invalid x509 leaf certificate using CA { k } . Unmatching private key, the chain will be removed" )
9595 continue
9696
97- chain = pem_list_to_der_list (v ) if type ( v [ 0 ]) == str and v [ 0 ]. startswith ( "-----BEGIN CERTIFICATE-----" ) else v
97+ chain = to_der_list (v )
9898
9999 if verify_x509_attestation_chain (chain ):
100100 self .relying_party_certificate_chains_by_ca [k ] = chain
@@ -104,14 +104,51 @@ def __init__(
104104
105105 self .private_keys = private_keys
106106
107+ def _verify_chain (self , x5c : list [str ]) -> bool :
108+ """
109+ Verify the x5c chain.
110+ :param x5c: The x5c chain to verify.
111+ :return: True if the chain is valid, False otherwise.
112+ """
113+ der_chain = [to_DER_cert (cert ) for cert in x5c ]
114+
115+ if len (der_chain ) > 1 and not verify_x509_attestation_chain (der_chain ):
116+ logger .error (f"Invalid x509 certificate chain. Chain validation failed" )
117+ return False
118+
119+ issuer = get_trust_anchor_from_x5c (der_chain )
120+
121+ if not issuer :
122+ logger .error ("Invalid x509 certificate chain. Issuer not found" )
123+ return False
124+
125+ if not issuer in self .certificate_authorities :
126+ logger .error ("Invalid x509 certificate chain. Issuer not found in the list of trusted CAs" )
127+ return False
128+
129+ issuer_cert = self .certificate_authorities [issuer ]
130+
131+ try :
132+ issuer_jwk = parse_certificate (issuer_cert )
133+ chain_jwks = parse_x5c_keys (der_chain )
134+ except Exception as e :
135+ logger .error (f"Invalid x509 certificate chain. Parsing failed: { e } " )
136+ return False
137+
138+ if not issuer_jwk .thumbprint == chain_jwks [- 1 ].thumbprint :
139+ logger .error ("Invalid x509 certificate chain. Issuer thumbprint does not match" )
140+ return False
141+
142+ return True
143+
107144 def extract_and_update_trust_materials (
108145 self , issuer : str , trust_source : TrustSourceData
109146 ) -> TrustSourceData :
110147 # Return the first valid chain
148+
111149 for ca , chain in self .relying_party_certificate_chains_by_ca .items ():
112- if not verify_x509_attestation_chain (chain ):
113- logger .error (f"Invalid x509 certificate chain using CA { ca } . Chain validation failed, the chain will be removed" )
114- del self .relying_party_certificate_chains_by_ca [ca ]
150+ if not self ._verify_chain (chain ):
151+ logger .error (f"Invalid x509 certificate chain using CA { ca } . Chain will be ignored" )
115152 continue
116153
117154 exp = get_expiry_date_from_x5c (chain )
@@ -120,7 +157,7 @@ def extract_and_update_trust_materials(
120157 X509Handler ._TRUST_TYPE ,
121158 TrustEvaluationType (
122159 attribute_name = "x5c" ,
123- x5c = der_list_to_pem_list (chain ),
160+ x5c = to_pem_list (chain ),
124161 expiration_date = exp ,
125162 jwks = self .private_keys ,
126163 trust_handler_name = self .name ,
@@ -136,47 +173,18 @@ def validate_trust_material(
136173 x5c : list [str ],
137174 trust_source : TrustSourceData ,
138175 ) -> tuple [bool , TrustSourceData ]:
139- # TODO: qui c'è del lavoro veramente sporco da fare.
140- # Bisogna
141- # (1) normalizzare la rappresentazione della chain a DER; per fare questo bisogna fare inferenza se PEM o Base64+DER
142- # (2) normalizzare il salvatagggio della chain a PEM
143- # (3) incrociare le dita che MDOC non si sfasci...
144- der_chain = [to_DER_cert (cert ) for cert in x5c ]
145- pem_chain = der_list_to_pem_list (der_chain )
146-
147- if len (der_chain ) > 1 and not verify_x509_attestation_chain (der_chain ):
148- logger .error (f"Invalid x509 certificate chain. Chain validation failed" )
149- return False , trust_source
150-
151- issuer = get_trust_anchor_from_x5c (der_chain )
152-
153- if not issuer :
154- logger .error ("Invalid x509 certificate chain. Issuer not found" )
155- return False , trust_source
156-
157- if not issuer in self .certificate_authorities :
158- logger .error ("Invalid x509 certificate chain. Issuer not found in the list of trusted CAs" )
159- return False , trust_source
160-
161- issuer_pem = self .certificate_authorities [issuer ]
176+ chain_jwks = parse_x5c_keys (x5c )
177+ valid = self ._verify_chain (x5c )
162178
163- try :
164- issuer_jwk = parse_pem (issuer_pem )
165- chain_jwks = parse_x5c_keys (x5c )
166- except Exception as e :
167- logger .error ("Invalid x509 certificate chain. Parsing failed: {e}" )
168- return False , trust_source
169-
170- if not issuer_jwk .thumbprint == chain_jwks [- 1 ].thumbprint :
171- logger .error ("Invalid x509 certificate chain. Issuer thumbprint does not match" )
179+ if not valid :
172180 return False , trust_source
173181
174182 trust_source .add_trust_param (
175183 "x509" ,
176184 TrustEvaluationType (
177185 attribute_name = self .get_handled_trust_material_name (),
178- x5c = pem_chain ,
179- expiration_date = get_expiry_date_from_x5c (der_chain ),
186+ x5c = to_pem_list ( x5c ) ,
187+ expiration_date = get_expiry_date_from_x5c (x5c ),
180188 jwks = chain_jwks ,
181189 trust_handler_name = self .name ,
182190 )
0 commit comments