@@ -134,7 +134,7 @@ int kr_rrset_validate(kr_rrset_validation_ctx_t *vctx, knot_rrset_t *covered)
134
134
memset (& vctx -> rrs_counters , 0 , sizeof (vctx -> rrs_counters ));
135
135
for (unsigned i = 0 ; i < vctx -> keys -> rrs .count ; ++ i ) {
136
136
int ret = kr_rrset_validate_with_key (vctx , covered , i , NULL );
137
- if (ret == 0 ) {
137
+ if (ret == 0 || ret == kr_error ( E2BIG ) ) {
138
138
return ret ;
139
139
}
140
140
}
@@ -240,6 +240,29 @@ struct kr_svldr_ctx * kr_svldr_new_ctx(const knot_rrset_t *ds, knot_rrset_t *dns
240
240
return NULL ;
241
241
}
242
242
243
+ /// Return if we want to afford yet another crypto-validation (and account it).
244
+ static bool check_crypto_limit (const kr_rrset_validation_ctx_t * vctx )
245
+ {
246
+ if (vctx -> limit_crypto_remains == NULL )
247
+ return true; // no limiting
248
+ if (* vctx -> limit_crypto_remains > 0 ) {
249
+ -- * vctx -> limit_crypto_remains ;
250
+ return true;
251
+ }
252
+ // We got over limit. There are optional actions to do.
253
+ if (vctx -> log_qry && kr_log_is_debug_qry (VALIDATOR , vctx -> log_qry )) {
254
+ auto_free char * name_str = kr_dname_text (vctx -> zone_name );
255
+ kr_log_q (vctx -> log_qry , VALIDATOR ,
256
+ "expensive crypto limited, mitigating CVE-2023-50387, current zone: %s\n" ,
257
+ name_str );
258
+ }
259
+ if (vctx -> log_qry && vctx -> log_qry -> request ) {
260
+ kr_request_set_extended_error (vctx -> log_qry -> request , KNOT_EDNS_EDE_BOGUS ,
261
+ "EAIE: expensive crypto limited, mitigating CVE-2023-50387" );
262
+ }
263
+ return false;
264
+ }
265
+
243
266
static int kr_svldr_rrset_with_key (knot_rrset_t * rrs , const knot_rdataset_t * rrsigs ,
244
267
kr_rrset_validation_ctx_t * vctx , const kr_svldr_key_t * key )
245
268
{
@@ -258,6 +281,8 @@ static int kr_svldr_rrset_with_key(knot_rrset_t *rrs, const knot_rdataset_t *rrs
258
281
} else if (retv != 0 ) {
259
282
continue ;
260
283
}
284
+ if (!check_crypto_limit (vctx ))
285
+ return vctx -> result = kr_error (E2BIG );
261
286
// We only expect non-expanded wildcard records in input;
262
287
// that also means we don't need to perform non-existence proofs.
263
288
const int trim_labels = (val_flgs & FLG_WILDCARD_EXPANSION ) ? 1 : 0 ;
@@ -282,7 +307,7 @@ int kr_svldr_rrset(knot_rrset_t *rrs, const knot_rdataset_t *rrsigs,
282
307
}
283
308
for (ssize_t i = 0 ; i < ctx -> keys .len ; ++ i ) {
284
309
kr_svldr_rrset_with_key (rrs , rrsigs , & ctx -> vctx , & ctx -> keys .at [i ]);
285
- if (ctx -> vctx .result == 0 )
310
+ if (ctx -> vctx .result == 0 || ctx -> vctx . result == kr_error ( E2BIG ) )
286
311
break ;
287
312
}
288
313
return ctx -> vctx .result ;
@@ -356,9 +381,8 @@ static int kr_rrset_validate_with_key(kr_rrset_validation_ctx_t *vctx,
356
381
int retv = validate_rrsig_rr (& val_flgs , covered_labels , rdata_j ,
357
382
key_alg , keytag , vctx );
358
383
if (retv == kr_error (EAGAIN )) {
359
- kr_dnssec_key_free (& created_key );
360
384
vctx -> result = retv ;
361
- return retv ;
385
+ goto finish ;
362
386
} else if (retv != 0 ) {
363
387
continue ;
364
388
}
@@ -368,6 +392,10 @@ static int kr_rrset_validate_with_key(kr_rrset_validation_ctx_t *vctx,
368
392
break ;
369
393
}
370
394
}
395
+ if (!check_crypto_limit (vctx )) {
396
+ vctx -> result = kr_error (E2BIG );
397
+ goto finish ;
398
+ }
371
399
if (kr_check_signature (rdata_j , key , covered , trim_labels ) != 0 ) {
372
400
vctx -> rrs_counters .crypto_invalid ++ ;
373
401
continue ;
@@ -392,15 +420,15 @@ static int kr_rrset_validate_with_key(kr_rrset_validation_ctx_t *vctx,
392
420
393
421
trim_ttl (covered , rdata_j , vctx );
394
422
395
- kr_dnssec_key_free (& created_key );
396
- vctx -> result = kr_ok ();
397
423
kr_rank_set (& vctx -> rrs -> at [i ]-> rank , KR_RANK_SECURE ); /* upgrade from bogus */
398
- return vctx -> result ;
424
+ vctx -> result = kr_ok ();
425
+ goto finish ;
399
426
}
400
427
}
401
428
/* No applicable key found, cannot be validated. */
402
- kr_dnssec_key_free (& created_key );
403
429
vctx -> result = kr_error (ENOENT );
430
+ finish :
431
+ kr_dnssec_key_free (& created_key );
404
432
return vctx -> result ;
405
433
}
406
434
@@ -448,7 +476,7 @@ int kr_dnskeys_trusted(kr_rrset_validation_ctx_t *vctx, const knot_rdataset_t *s
448
476
if (ret == 0 )
449
477
ret = kr_svldr_rrset_with_key (keys , sigs , vctx , & key );
450
478
svldr_key_del (& key );
451
- if (ret == 0 ) {
479
+ if (ret == 0 || ret == kr_error ( E2BIG ) ) {
452
480
kr_assert (vctx -> result == 0 );
453
481
return vctx -> result ;
454
482
}
0 commit comments