88import ch .admin .bag .covidcertificate .backend .verification .check .ws .model .RevokedCertificatesRepository ;
99import ch .admin .bag .covidcertificate .backend .verification .check .ws .model .RevokedCertificatesRepository .RevokedCertificates ;
1010import ch .admin .bag .covidcertificate .backend .verification .check .ws .model .TrustListConfig ;
11+ import ch .admin .bag .covidcertificate .sdk .core .data .ErrorCodes ;
1112import ch .admin .bag .covidcertificate .sdk .core .decoder .CertificateDecoder ;
1213import ch .admin .bag .covidcertificate .sdk .core .models .healthcert .CertificateHolder ;
1314import ch .admin .bag .covidcertificate .sdk .core .models .state .CheckNationalRulesState ;
1415import ch .admin .bag .covidcertificate .sdk .core .models .state .CheckRevocationState ;
1516import ch .admin .bag .covidcertificate .sdk .core .models .state .CheckSignatureState ;
1617import ch .admin .bag .covidcertificate .sdk .core .models .state .DecodeState ;
18+ import ch .admin .bag .covidcertificate .sdk .core .models .state .SuccessState .WalletSuccessState ;
1719import ch .admin .bag .covidcertificate .sdk .core .models .state .VerificationState ;
20+ import ch .admin .bag .covidcertificate .sdk .core .models .state .VerificationState .ERROR ;
1821import ch .admin .bag .covidcertificate .sdk .core .models .state .VerificationState .INVALID ;
22+ import ch .admin .bag .covidcertificate .sdk .core .models .state .VerificationState .LOADING ;
1923import ch .admin .bag .covidcertificate .sdk .core .models .state .VerificationState .SUCCESS ;
2024import ch .admin .bag .covidcertificate .sdk .core .models .trustlist .ActiveModes ;
2125import ch .admin .bag .covidcertificate .sdk .core .models .trustlist .DisplayRule ;
@@ -66,6 +70,10 @@ public class VerificationService {
6670
6771 private final RestTemplate rt ;
6872
73+ private static final VerificationState DUMMY_SUCCESS_STATE =
74+ new VerificationState .SUCCESS (
75+ new WalletSuccessState (false , null , new ArrayList <>(), null , null ), false );
76+
6977 @ Value ("${verifier.baseurl}" )
7078 private String verifierBaseUrl ;
7179
@@ -81,6 +89,8 @@ public class VerificationService {
8189 @ Value ("${verifier.api-key:}" )
8290 private String apiKey ;
8391
92+ private static final String SHOW_RENEW_BANNER = "showRenewBanner" ;
93+
8494 public VerificationService (RestTemplate rt ) {
8595 this .rt = rt ;
8696 }
@@ -93,12 +103,15 @@ public void init() {
93103 public void updateTrustListConfig () {
94104 try {
95105 logger .info ("updating trust list config" );
96- Jwks jwks = getDSCs ();
106+ Jwks jwks = getDSCs (null );
107+ Jwks jwksCh = getDSCs ("CH" );
97108 RevokedCertificatesRepository revokedCerts = getRevokedCerts ();
98109 RuleSet nationalRules = getNationalRules ();
99110 this .trustListConfig .setTrustList (new TrustList (jwks , revokedCerts , nationalRules ));
100111 this .trustListConfig .setRevokedCertificatesRepository (revokedCerts );
101112 this .trustListConfig .setLastSync (Instant .now ());
113+ this .trustListConfig .setRenewalTrustList (
114+ new TrustList (jwksCh , revokedCerts , nationalRules ));
102115 logger .info ("done updating trust list config" );
103116 } catch (Exception e ) {
104117 logger .error ("failed to update trust list config" , e );
@@ -111,17 +124,24 @@ public void updateTrustListConfig() {
111124 *
112125 * @return a JWKs object as required by the SDK-core mapped from a list of ClientCerts
113126 */
114- private Jwks getDSCs () throws URISyntaxException {
115- logger .info ("Updating list of DSCs" );
127+ private Jwks getDSCs (String country ) throws URISyntaxException {
128+ if (country == null ) {
129+ logger .info ("Updating list of DSCs for all countries" );
130+ } else {
131+ logger .info ("Updating list of DSCs for {}" , country );
132+ }
116133 Map <String , String > params = getKeyUpdatesParams ();
134+ if (country != null ) {
135+ params .put ("country" , country );
136+ }
117137 List <Jwk > jwkList = new ArrayList <>();
118138 boolean done = false ;
119139 int it = 0 ;
120140 do {
121141 final ResponseEntity <Jwks > response =
122142 rt .exchange (getRequestEntity (dscEndpoint , params ), Jwks .class );
123143 var body = response .getBody ();
124- if (body != null ){
144+ if (body != null ) {
125145 jwkList .addAll (body .getCerts ());
126146 }
127147
@@ -172,7 +192,7 @@ private RevokedCertificatesRepository getRevokedCerts() throws URISyntaxExceptio
172192 rt .exchange (
173193 getRequestEntity (revocationEndpoint , params ), RevokedCertificates .class );
174194 RevokedCertificates revokedCerts = response .getBody ();
175- if (revokedCerts == null ){
195+ if (revokedCerts == null ) {
176196 logger .error ("Failed to get revoked certificates" );
177197 throw new NullPointerException ("Failed to get revoked certificates" );
178198 }
@@ -188,11 +208,11 @@ private RevokedCertificatesRepository getRevokedCerts() throws URISyntaxExceptio
188208 rt .exchange (
189209 getRequestEntity (revocationEndpoint , params ),
190210 RevokedCertificates .class );
191- if (response .getBody () != null ) {
211+ if (response .getBody () != null ) {
192212 var body = response .getBody ();
193- if (body != null ){
213+ if (body != null ) {
194214 repo .addCertificates (body .getRevokedCerts ());
195- }else {
215+ } else {
196216 logger .error ("Failed to fetch some of the revoked certificates" );
197217 }
198218 }
@@ -203,7 +223,7 @@ private RevokedCertificatesRepository getRevokedCerts() throws URISyntaxExceptio
203223
204224 it ++;
205225 }
206- logger .info ("downloaded {} revoked certificates" , revokedCerts .getRevokedCerts ().size ());
226+ logger .info ("downloaded {} revoked certificates" , revokedCerts .getRevokedCerts ().size ());
207227
208228 return repo ;
209229 }
@@ -220,7 +240,7 @@ private RuleSet getNationalRules() throws URISyntaxException {
220240 getRequestEntity (rulesEndpoint , new HashMap <>()),
221241 IntermediateRuleSet .class )
222242 .getBody ();
223- if (intermediateRuleSet == null ){
243+ if (intermediateRuleSet == null ) {
224244 logger .error ("Failed to fetch national rules" );
225245 throw new NullPointerException ("intermediateRuleSet is null" );
226246 }
@@ -248,7 +268,12 @@ private RuleSet getNationalRules() throws URISyntaxException {
248268 .map (rule -> new DisplayRule (rule .getId (), rule .getLogic ()))
249269 .collect (Collectors .toList ());
250270 ModeRules intermediateModeRules = intermediateRuleSet .getModeRules ();
251- ch .admin .bag .covidcertificate .sdk .core .models .trustlist .ModeRules sdkModeRules = new ch .admin .bag .covidcertificate .sdk .core .models .trustlist .ModeRules (intermediateModeRules .getActiveModes (), intermediateModeRules .getWalletActiveModes (), intermediateModeRules .getVerifierActiveModes (), intermediateModeRules .getLogic ());
271+ ch .admin .bag .covidcertificate .sdk .core .models .trustlist .ModeRules sdkModeRules =
272+ new ch .admin .bag .covidcertificate .sdk .core .models .trustlist .ModeRules (
273+ intermediateModeRules .getActiveModes (),
274+ intermediateModeRules .getWalletActiveModes (),
275+ intermediateModeRules .getVerifierActiveModes (),
276+ intermediateModeRules .getLogic ());
252277 logger .info ("downloaded {} rules" , rules .size ());
253278
254279 return new RuleSet (
@@ -303,10 +328,53 @@ public VerificationState verifyDccAllModes(CertificateHolder certificateHolder)
303328 : getOutdatedTrustListState (state );
304329 }
305330
306- public VerificationState verifyDccSingleMode (CertificateHolder certificateHolder , String mode ){
331+ public VerificationState verifyDccSingleMode (CertificateHolder certificateHolder , String mode ) {
307332 TrustList trustList = trustListConfig .getTrustList ();
308333 VerificationState state =
309- VerifyWrapper .verifyVerifier (certificateVerifier , certificateHolder , trustList , mode );
334+ VerifyWrapper .verifyVerifier (
335+ certificateVerifier , certificateHolder , trustList , mode );
336+ return !trustListConfig .isOutdated () || state instanceof VerificationState .ERROR
337+ ? state
338+ : getOutdatedTrustListState (state );
339+ }
340+
341+ public VerificationState verifyDccForRenewal (CertificateHolder certificateHolder ) {
342+ TrustList trustList = trustListConfig .getRenewalTrustList ();
343+ VerificationState state =
344+ VerifyWrapper .verifyWallet (certificateVerifier , certificateHolder , trustList );
345+ String renewBanner = null ;
346+ if (state instanceof ERROR || state instanceof LOADING ) {
347+ return state ;
348+ } else if (state instanceof SUCCESS ) {
349+ renewBanner =
350+ ((WalletSuccessState ) ((SUCCESS ) state ).getSuccessState ()).getShowRenewBanner ();
351+ } else if (state instanceof INVALID ) {
352+ renewBanner = ((INVALID ) state ).getShowRenewBanner ();
353+ }
354+ if (!SHOW_RENEW_BANNER .equals (renewBanner )) {
355+ return new INVALID (null , null , null , null , null );
356+ }
357+ // Certain verification failures are accepted in the renewal case as long as it's not
358+ // revoked
359+ if (state instanceof INVALID
360+ && (((INVALID ) state ).getRevocationState ()
361+ instanceof CheckRevocationState .SUCCESS )) {
362+ var signatureState = ((INVALID ) state ).getSignatureState ();
363+
364+ // As long as the signature is ok, we can ignore rule failures
365+ if (signatureState instanceof CheckSignatureState .SUCCESS ) {
366+ state = DUMMY_SUCCESS_STATE ;
367+ // If the signature has expired but is otherwise ok, the cert is also approved for
368+ // renewal
369+ } else if (signatureState instanceof CheckSignatureState .INVALID ) {
370+ var invalidState = (CheckSignatureState .INVALID ) signatureState ;
371+ if (invalidState
372+ .getSignatureErrorCode ()
373+ .equals (ErrorCodes .SIGNATURE_TIMESTAMP_EXPIRED )) {
374+ state = DUMMY_SUCCESS_STATE ;
375+ }
376+ }
377+ }
310378 return !trustListConfig .isOutdated () || state instanceof VerificationState .ERROR
311379 ? state
312380 : getOutdatedTrustListState (state );
@@ -343,16 +411,16 @@ private VerificationState getOutdatedTrustListState(VerificationState originalSt
343411 signatureState ,
344412 new CheckRevocationState .INVALID (TRUST_LIST_OUTDATED ),
345413 new CheckNationalRulesState .INVALID (
346- NationalRulesError .UNKNOWN_RULE_FAILED , false , TRUST_LIST_OUTDATED ),
347- null );
414+ NationalRulesError .UNKNOWN_RULE_FAILED , false , TRUST_LIST_OUTDATED , "" ),
415+ null ,
416+ "" );
348417 }
349418
350- public List <ActiveModes > getWalletVerificationModes (){
419+ public List <ActiveModes > getWalletVerificationModes () {
351420 return trustListConfig .getTrustList ().getRuleSet ().getModeRules ().getActiveModes ();
352421 }
353422
354- public List <ActiveModes > getVerifierVerificationModes (){
423+ public List <ActiveModes > getVerifierVerificationModes () {
355424 return trustListConfig .getTrustList ().getRuleSet ().getModeRules ().getVerifierActiveModes ();
356425 }
357-
358426}
0 commit comments