diff --git a/lib/dnssec/nsec3.c b/lib/dnssec/nsec3.c
index 8fe13cbaf1b1418a153837716057491e4c01259b..7f1328d97f7f83ed995095afceabb9b3bf808313 100644
--- a/lib/dnssec/nsec3.c
+++ b/lib/dnssec/nsec3.c
@@ -208,20 +208,43 @@ static int covers_name(int *flags, const knot_rrset_t *nsec3, const knot_dname_t
 		goto fail;
 	}
 
-	if ((owner_hash.size != name_hash.size) ||
-	    (memcmp(owner_hash.data, name_hash.data, owner_hash.size) >= 0)) {
-		goto fail;
-	}
-
 	uint8_t next_size = 0;
 	uint8_t *next_hash = NULL;
 	knot_nsec3_next_hashed(&nsec3->rrs, 0, &next_hash, &next_size);
 
-	if ((name_hash.size != next_size) ||
-	    (memcmp(name_hash.data, next_hash, name_hash.size) >= 0)) {
+	if ((owner_hash.size != next_size) || (name_hash.size != next_size)) {
+		/* All hash lengths must be same. */
 		goto fail;
 	}
 
+	const uint8_t *ownrd = owner_hash.data;
+	const uint8_t *nextd = next_hash;
+	if (memcmp(ownrd, nextd, next_size) < 0) {
+		/*
+		 * 0 (...) owner ... next (...) MAX
+		 *                ^
+		 *                name
+		 * ==>
+		 * (owner < name) && (name < next)
+		 */
+		if ((memcmp(ownrd, name_hash.data, next_size) >= 0) ||
+		    (memcmp(name_hash.data, nextd, next_size) >= 0)) {
+			goto fail;
+		}
+	} else {
+		/*
+		 * owner ... MAX, 0 ... next
+		 *        ^     ^    ^
+		 *        name  name name
+		 * =>
+		 * (owner < name) || (name < next)
+		 */
+		if ((memcmp(ownrd, name_hash.data, next_size) >= 0) &&
+		    (memcmp(name_hash.data, nextd, next_size) >= 0)) {
+			goto fail;
+		}
+	}
+
 	*flags |= FLG_NAME_COVERED;
 
 	uint8_t nsec3_flags = knot_nsec3_flags(&nsec3->rrs, 0);
diff --git a/lib/layer/validate.c b/lib/layer/validate.c
index 85a5237f56b2e9179abe208830d1fd7df3b36c85..f5bb333926b9e261cfd60c19960122f9a20466bb 100644
--- a/lib/layer/validate.c
+++ b/lib/layer/validate.c
@@ -361,7 +361,6 @@ static int validate(knot_layer_t *ctx, knot_pkt_t *pkt)
 
 	/* Validate non-existence proof if not positive answer. */
 	if (knot_wire_get_rcode(pkt->wire) == KNOT_RCODE_NXDOMAIN) {
-#warning TODO: validate NSECx proof, RRSIGs will be checked later if it matches
 		if (!has_nsec3) {
 			ret = kr_nsec_name_error_response_check(pkt, KNOT_AUTHORITY, qry->sname, &req->pool);
 		} else {