diff --git a/SOURCES/bind99-CVE-2017-3142+3143.patch b/SOURCES/bind99-CVE-2017-3142+3143.patch
new file mode 100644
index 0000000..a0190f4
--- /dev/null
+++ b/SOURCES/bind99-CVE-2017-3142+3143.patch
@@ -0,0 +1,497 @@
+diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c
+index 00a0080..336c4da 100644
+--- a/lib/dns/dnssec.c
++++ b/lib/dns/dnssec.c
+@@ -982,6 +982,8 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
+ 	mctx = msg->mctx;
+ 
+ 	msg->verify_attempted = 1;
++	msg->verified_sig = 0;
++	msg->sig0status = dns_tsigerror_badsig;
+ 
+ 	if (is_response(msg)) {
+ 		if (msg->query.base == NULL)
+@@ -1076,6 +1078,7 @@ dns_dnssec_verifymessage(isc_buffer_t *source, dns_message_t *msg,
+ 	}
+ 
+ 	msg->verified_sig = 1;
++	msg->sig0status = dns_rcode_noerror;
+ 
+ 	dst_context_destroy(&ctx);
+ 	dns_rdata_freestruct(&sig);
+diff --git a/lib/dns/message.c b/lib/dns/message.c
+index 1417067..0621175 100644
+--- a/lib/dns/message.c
++++ b/lib/dns/message.c
+@@ -3052,12 +3052,19 @@ dns_message_signer(dns_message_t *msg, dns_name_t *signer) {
+ 
+ 		result = dns_rdata_tostruct(&rdata, &tsig, NULL);
+ 		INSIST(result == ISC_R_SUCCESS);
+-		if (msg->tsigstatus != dns_rcode_noerror)
++		if (msg->verified_sig &&
++		    msg->tsigstatus == dns_rcode_noerror &&
++		    tsig.error == dns_rcode_noerror)
++		{
++			result = ISC_R_SUCCESS;
++		} else if ((!msg->verified_sig) ||
++			   (msg->tsigstatus != dns_rcode_noerror))
++		{
+ 			result = DNS_R_TSIGVERIFYFAILURE;
+-		else if (tsig.error != dns_rcode_noerror)
++		} else {
++			INSIST(tsig.error != dns_rcode_noerror);
+ 			result = DNS_R_TSIGERRORSET;
+-		else
+-			result = ISC_R_SUCCESS;
++		}
+ 		dns_rdata_freestruct(&tsig);
+ 
+ 		if (msg->tsigkey == NULL) {
+diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
+index 3239bff..7b91d1e 100644
+--- a/lib/dns/tsig.c
++++ b/lib/dns/tsig.c
+@@ -941,11 +941,20 @@ dns_tsig_sign(dns_message_t *msg) {
+ 		isc_buffer_putuint48(&otherbuf, tsig.timesigned);
+ 	}
+ 
+-	if (key->key != NULL && tsig.error != dns_tsigerror_badsig) {
++	if ((key->key != NULL) &&
++	    (tsig.error != dns_tsigerror_badsig) &&
++	    (tsig.error != dns_tsigerror_badkey))
++	{
+ 		unsigned char header[DNS_MESSAGE_HEADERLEN];
+ 		isc_buffer_t headerbuf;
+ 		isc_uint16_t digestbits;
+ 
++		/*
++		 * If it is a response, we assume that the request MAC
++		 * has validated at this point. This is why we include a
++		 * MAC length > 0 in the reply.
++		 */
++
+ 		ret = dst_context_create3(key->key, mctx,
+ 					  DNS_LOGCATEGORY_DNSSEC,
+ 					  ISC_TRUE, &ctx);
+@@ -953,7 +962,7 @@ dns_tsig_sign(dns_message_t *msg) {
+ 			return (ret);
+ 
+ 		/*
+-		 * If this is a response, digest the query signature.
++		 * If this is a response, digest the request's MAC.
+ 		 */
+ 		if (response) {
+ 			dns_rdata_t querytsigrdata = DNS_RDATA_INIT;
+@@ -1083,6 +1092,17 @@ dns_tsig_sign(dns_message_t *msg) {
+ 		dst_context_destroy(&ctx);
+ 		digestbits = dst_key_getbits(key->key);
+ 		if (digestbits != 0) {
++			/*
++			 * XXXRAY: Is this correct? What is the
++			 * expected behavior when digestbits is not an
++			 * integral multiple of 8? It looks like bytes
++			 * should either be (digestbits/8) or
++			 * (digestbits+7)/8.
++			 *
++			 * In any case, for current algorithms,
++			 * digestbits are an integral multiple of 8, so
++			 * it has the same effect as (digestbits/8).
++			 */
+ 			unsigned int bytes = (digestbits + 1) / 8;
+ 			if (response && bytes < querytsig.siglen)
+ 				bytes = querytsig.siglen;
+@@ -1196,6 +1216,8 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
+ 	REQUIRE(tsigkey == NULL || VALID_TSIG_KEY(tsigkey));
+ 
+ 	msg->verify_attempted = 1;
++	msg->verified_sig = 0;
++	msg->tsigstatus = dns_tsigerror_badsig;
+ 
+ 	if (msg->tcp_continuation) {
+ 		if (tsigkey == NULL || msg->querytsig == NULL)
+@@ -1294,19 +1316,6 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
+ 	key = tsigkey->key;
+ 
+ 	/*
+-	 * Is the time ok?
+-	 */
+-	if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
+-		msg->tsigstatus = dns_tsigerror_badtime;
+-		tsig_log(msg->tsigkey, 2, "signature has expired");
+-		return (DNS_R_CLOCKSKEW);
+-	} else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
+-		msg->tsigstatus = dns_tsigerror_badtime;
+-		tsig_log(msg->tsigkey, 2, "signature is in the future");
+-		return (DNS_R_CLOCKSKEW);
+-	}
+-
+-	/*
+ 	 * Check digest length.
+ 	 */
+ 	alg = dst_key_alg(key);
+@@ -1315,31 +1324,19 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
+ 		return (ret);
+ 	if (alg == DST_ALG_HMACMD5 || alg == DST_ALG_HMACSHA1 ||
+ 	    alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
+-	    alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) {
+-		isc_uint16_t digestbits = dst_key_getbits(key);
++	    alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
++	{
+ 		if (tsig.siglen > siglen) {
+-			tsig_log(msg->tsigkey, 2, "signature length to big");
++			tsig_log(msg->tsigkey, 2, "signature length too big");
+ 			return (DNS_R_FORMERR);
+ 		}
+ 		if (tsig.siglen > 0 &&
+-		    (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2))) {
++		    (tsig.siglen < 10 || tsig.siglen < ((siglen + 1) / 2)))
++		{
+ 			tsig_log(msg->tsigkey, 2,
+ 				 "signature length below minimum");
+ 			return (DNS_R_FORMERR);
+ 		}
+-		if (tsig.siglen > 0 && digestbits != 0 &&
+-		    tsig.siglen < ((digestbits + 1) / 8)) {
+-			msg->tsigstatus = dns_tsigerror_badtrunc;
+-			tsig_log(msg->tsigkey, 2,
+-				 "truncated signature length too small");
+-			return (DNS_R_TSIGVERIFYFAILURE);
+-		}
+-		if (tsig.siglen > 0 && digestbits == 0 &&
+-		    tsig.siglen < siglen) {
+-			msg->tsigstatus = dns_tsigerror_badtrunc;
+-			tsig_log(msg->tsigkey, 2, "signature length too small");
+-			return (DNS_R_TSIGVERIFYFAILURE);
+-		}
+ 	}
+ 
+ 	if (tsig.siglen > 0) {
+@@ -1451,34 +1448,92 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
+ 
+ 		ret = dst_context_verify(ctx, &sig_r);
+ 		if (ret == DST_R_VERIFYFAILURE) {
+-			msg->tsigstatus = dns_tsigerror_badsig;
+ 			ret = DNS_R_TSIGVERIFYFAILURE;
+ 			tsig_log(msg->tsigkey, 2,
+ 				 "signature failed to verify(1)");
+ 			goto cleanup_context;
+-		} else if (ret != ISC_R_SUCCESS)
++		} else if (ret != ISC_R_SUCCESS) {
+ 			goto cleanup_context;
+-
+-		dst_context_destroy(&ctx);
++		}
+ 	} else if (tsig.error != dns_tsigerror_badsig &&
+ 		   tsig.error != dns_tsigerror_badkey) {
+-		msg->tsigstatus = dns_tsigerror_badsig;
+ 		tsig_log(msg->tsigkey, 2, "signature was empty");
+ 		return (DNS_R_TSIGVERIFYFAILURE);
+ 	}
+ 
+-	msg->tsigstatus = dns_rcode_noerror;
++	/*
++	 * Here at this point, the MAC has been verified. Even if any of
++	 * the following code returns a TSIG error, the reply will be
++	 * signed and WILL always include the request MAC in the digest
++	 * computation.
++	 */
++
++	/*
++	 * Is the time ok?
++	 */
++	if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
++		msg->tsigstatus = dns_tsigerror_badtime;
++		tsig_log(msg->tsigkey, 2, "signature has expired");
++		ret = DNS_R_CLOCKSKEW;
++		goto cleanup_context;
++	} else if (now + msg->timeadjust < tsig.timesigned - tsig.fudge) {
++		msg->tsigstatus = dns_tsigerror_badtime;
++		tsig_log(msg->tsigkey, 2, "signature is in the future");
++		ret = DNS_R_CLOCKSKEW;
++		goto cleanup_context;
++	}
++
++	if (
++#ifndef PK11_MD5_DISABLE
++	    alg == DST_ALG_HMACMD5 ||
++#endif
++	    alg == DST_ALG_HMACSHA1 ||
++	    alg == DST_ALG_HMACSHA224 || alg == DST_ALG_HMACSHA256 ||
++	    alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512)
++	{
++		isc_uint16_t digestbits = dst_key_getbits(key);
++
++		/*
++		 * XXXRAY: Is this correct? What is the expected
++		 * behavior when digestbits is not an integral multiple
++		 * of 8? It looks like bytes should either be
++		 * (digestbits/8) or (digestbits+7)/8.
++		 *
++		 * In any case, for current algorithms, digestbits are
++		 * an integral multiple of 8, so it has the same effect
++		 * as (digestbits/8).
++		 */
++		if (tsig.siglen > 0 && digestbits != 0 &&
++		    tsig.siglen < ((digestbits + 1) / 8))
++		{
++			msg->tsigstatus = dns_tsigerror_badtrunc;
++			tsig_log(msg->tsigkey, 2,
++				 "truncated signature length too small");
++			ret = DNS_R_TSIGVERIFYFAILURE;
++			goto cleanup_context;
++		}
++		if (tsig.siglen > 0 && digestbits == 0 &&
++		    tsig.siglen < siglen)
++		{
++			msg->tsigstatus = dns_tsigerror_badtrunc;
++			tsig_log(msg->tsigkey, 2, "signature length too small");
++			ret = DNS_R_TSIGVERIFYFAILURE;
++			goto cleanup_context;
++		}
++	}
+ 
+ 	if (tsig.error != dns_rcode_noerror) {
++		msg->tsigstatus = tsig.error;
+ 		if (tsig.error == dns_tsigerror_badtime)
+-			return (DNS_R_CLOCKSKEW);
++			ret = DNS_R_CLOCKSKEW;
+ 		else
+-			return (DNS_R_TSIGERRORSET);
++			ret = DNS_R_TSIGERRORSET;
++		goto cleanup_context;
+ 	}
+ 
++	msg->tsigstatus = dns_rcode_noerror;
+ 	msg->verified_sig = 1;
+-
+-	return (ISC_R_SUCCESS);
++	ret = ISC_R_SUCCESS;
+ 
+ cleanup_context:
+ 	if (ctx != NULL)
+@@ -1503,6 +1558,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ 	isc_uint16_t addcount, id;
+ 	isc_boolean_t has_tsig = ISC_FALSE;
+ 	isc_mem_t *mctx;
++	unsigned int siglen;
++	unsigned int alg;
+ 
+ 	REQUIRE(source != NULL);
+ 	REQUIRE(msg != NULL);
+@@ -1510,12 +1567,16 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ 	REQUIRE(msg->tcp_continuation == 1);
+ 	REQUIRE(msg->querytsig != NULL);
+ 
++	msg->verified_sig = 0;
++	msg->tsigstatus = dns_tsigerror_badsig;
++
+ 	if (!is_response(msg))
+ 		return (DNS_R_EXPECTEDRESPONSE);
+ 
+ 	mctx = msg->mctx;
+ 
+ 	tsigkey = dns_message_gettsigkey(msg);
++	key = tsigkey->key;
+ 
+ 	/*
+ 	 * Extract and parse the previous TSIG
+@@ -1548,7 +1609,8 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ 		 * Do the key name and algorithm match that of the query?
+ 		 */
+ 		if (!dns_name_equal(keyname, &tsigkey->name) ||
+-		    !dns_name_equal(&tsig.algorithm, &querytsig.algorithm)) {
++		    !dns_name_equal(&tsig.algorithm, &querytsig.algorithm))
++		{
+ 			msg->tsigstatus = dns_tsigerror_badkey;
+ 			ret = DNS_R_TSIGVERIFYFAILURE;
+ 			tsig_log(msg->tsigkey, 2,
+@@ -1557,27 +1619,40 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ 		}
+ 
+ 		/*
+-		 * Is the time ok?
++		 * Check digest length.
+ 		 */
+-		isc_stdtime_get(&now);
+-
+-		if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
+-			msg->tsigstatus = dns_tsigerror_badtime;
+-			tsig_log(msg->tsigkey, 2, "signature has expired");
+-			ret = DNS_R_CLOCKSKEW;
+-			goto cleanup_querystruct;
+-		} else if (now + msg->timeadjust <
+-			   tsig.timesigned - tsig.fudge) {
+-			msg->tsigstatus = dns_tsigerror_badtime;
+-			tsig_log(msg->tsigkey, 2,
+-				 "signature is in the future");
+-			ret = DNS_R_CLOCKSKEW;
++		alg = dst_key_alg(key);
++		ret = dst_key_sigsize(key, &siglen);
++		if (ret != ISC_R_SUCCESS)
+ 			goto cleanup_querystruct;
++		if (
++#ifndef PK11_MD5_DISABLE
++			alg == DST_ALG_HMACMD5 ||
++#endif
++			alg == DST_ALG_HMACSHA1 ||
++			alg == DST_ALG_HMACSHA224 ||
++			alg == DST_ALG_HMACSHA256 ||
++			alg == DST_ALG_HMACSHA384 ||
++			alg == DST_ALG_HMACSHA512)
++		{
++			if (tsig.siglen > siglen) {
++				tsig_log(tsigkey, 2,
++					 "signature length too big");
++				ret = DNS_R_FORMERR;
++				goto cleanup_querystruct;
++			}
++			if (tsig.siglen > 0 &&
++			    (tsig.siglen < 10 ||
++			     tsig.siglen < ((siglen + 1) / 2)))
++			{
++				tsig_log(tsigkey, 2,
++					 "signature length below minimum");
++				ret = DNS_R_FORMERR;
++				goto cleanup_querystruct;
++			}
+ 		}
+ 	}
+ 
+-	key = tsigkey->key;
+-
+ 	if (msg->tsigctx == NULL) {
+ 		ret = dst_context_create3(key, mctx,
+ 					  DNS_LOGCATEGORY_DNSSEC,
+@@ -1670,10 +1745,12 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ 		sig_r.length = tsig.siglen;
+ 		if (tsig.siglen == 0) {
+ 			if (tsig.error != dns_rcode_noerror) {
+-				if (tsig.error == dns_tsigerror_badtime)
++				msg->tsigstatus = tsig.error;
++				if (tsig.error == dns_tsigerror_badtime) {
+ 					ret = DNS_R_CLOCKSKEW;
+-				else
++				} else {
+ 					ret = DNS_R_TSIGERRORSET;
++				}
+ 			} else {
+ 				tsig_log(msg->tsigkey, 2,
+ 					 "signature is empty");
+@@ -1684,29 +1761,111 @@ tsig_verify_tcp(isc_buffer_t *source, dns_message_t *msg) {
+ 
+ 		ret = dst_context_verify(msg->tsigctx, &sig_r);
+ 		if (ret == DST_R_VERIFYFAILURE) {
+-			msg->tsigstatus = dns_tsigerror_badsig;
+ 			tsig_log(msg->tsigkey, 2,
+ 				 "signature failed to verify(2)");
+ 			ret = DNS_R_TSIGVERIFYFAILURE;
+ 			goto cleanup_context;
++		} else if (ret != ISC_R_SUCCESS) {
++			goto cleanup_context;
+ 		}
+-		else if (ret != ISC_R_SUCCESS)
++
++		/*
++		 * Here at this point, the MAC has been verified. Even
++		 * if any of the following code returns a TSIG error,
++		 * the reply will be signed and WILL always include the
++		 * request MAC in the digest computation.
++		 */
++
++		/*
++		 * Is the time ok?
++		 */
++		isc_stdtime_get(&now);
++
++		if (now + msg->timeadjust > tsig.timesigned + tsig.fudge) {
++			msg->tsigstatus = dns_tsigerror_badtime;
++			tsig_log(msg->tsigkey, 2, "signature has expired");
++			ret = DNS_R_CLOCKSKEW;
++			goto cleanup_context;
++		} else if (now + msg->timeadjust <
++			   tsig.timesigned - tsig.fudge)
++		{
++			msg->tsigstatus = dns_tsigerror_badtime;
++			tsig_log(msg->tsigkey, 2,
++				 "signature is in the future");
++			ret = DNS_R_CLOCKSKEW;
+ 			goto cleanup_context;
++		}
+ 
+-		dst_context_destroy(&msg->tsigctx);
++		alg = dst_key_alg(key);
++		ret = dst_key_sigsize(key, &siglen);
++		if (ret != ISC_R_SUCCESS)
++			goto cleanup_context;
++		if (
++#ifndef PK11_MD5_DISABLE
++			alg == DST_ALG_HMACMD5 ||
++#endif
++			alg == DST_ALG_HMACSHA1 ||
++			alg == DST_ALG_HMACSHA224 ||
++			alg == DST_ALG_HMACSHA256 ||
++			alg == DST_ALG_HMACSHA384 ||
++			alg == DST_ALG_HMACSHA512)
++		{
++			isc_uint16_t digestbits = dst_key_getbits(key);
++
++			/*
++			 * XXXRAY: Is this correct? What is the
++			 * expected behavior when digestbits is not an
++			 * integral multiple of 8? It looks like bytes
++			 * should either be (digestbits/8) or
++			 * (digestbits+7)/8.
++			 *
++			 * In any case, for current algorithms,
++			 * digestbits are an integral multiple of 8, so
++			 * it has the same effect as (digestbits/8).
++			 */
++			if (tsig.siglen > 0 && digestbits != 0 &&
++			    tsig.siglen < ((digestbits + 1) / 8))
++			{
++				msg->tsigstatus = dns_tsigerror_badtrunc;
++				tsig_log(msg->tsigkey, 2,
++					 "truncated signature length "
++					 "too small");
++				ret = DNS_R_TSIGVERIFYFAILURE;
++				goto cleanup_context;
++			}
++			if (tsig.siglen > 0 && digestbits == 0 &&
++			    tsig.siglen < siglen)
++			{
++				msg->tsigstatus = dns_tsigerror_badtrunc;
++				tsig_log(msg->tsigkey, 2,
++					 "signature length too small");
++				ret = DNS_R_TSIGVERIFYFAILURE;
++				goto cleanup_context;
++			}
++		}
++
++		if (tsig.error != dns_rcode_noerror) {
++			msg->tsigstatus = tsig.error;
++			if (tsig.error == dns_tsigerror_badtime)
++				ret = DNS_R_CLOCKSKEW;
++			else
++				ret = DNS_R_TSIGERRORSET;
++			goto cleanup_context;
++		}
+ 	}
+ 
+ 	msg->tsigstatus = dns_rcode_noerror;
+-	return (ISC_R_SUCCESS);
++	msg->verified_sig = 1;
++	ret = ISC_R_SUCCESS;
+ 
+  cleanup_context:
+-	dst_context_destroy(&msg->tsigctx);
++	if (msg->tsigctx != NULL)
++		dst_context_destroy(&msg->tsigctx);
+ 
+  cleanup_querystruct:
+ 	dns_rdata_freestruct(&querytsig);
+ 
+ 	return (ret);
+-
+ }
+ 
+ isc_result_t
diff --git a/SPECS/bind.spec b/SPECS/bind.spec
index 79a6f63..f65cc3c 100644
--- a/SPECS/bind.spec
+++ b/SPECS/bind.spec
@@ -25,7 +25,7 @@ Summary:  The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) serv
 Name:     bind
 License:  ISC
 Version:  9.9.4
-Release:  50%{?PATCHVER}%{?PREVER}%{?dist}
+Release:  51%{?PATCHVER}%{?PREVER}%{?dist}
 Epoch:    32
 Url:      http://www.isc.org/products/BIND/
 Buildroot:%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
@@ -143,6 +143,8 @@ Patch179:bind99-CVE-2017-3136.patch
 Patch180:bind99-CVE-2017-3137.patch
 # commit 5e746ab61ed8158f784b86111fef95581a08b7dd ISC 3905
 Patch181:bind99-rh1416304.patch
+# ISC 4643
+Patch182: bind99-CVE-2017-3142+3143.patch
 
 # Native PKCS#11 functionality from 9.10
 Patch150:bind-9.9-allow_external_dnskey.patch
@@ -442,6 +444,7 @@ tar -xf %{SOURCE48} -C bin/tests/system/geoip/data
 %patch179 -p1 -b .CVE-2017-3136
 %patch180 -p1 -b .CVE-2017-3137
 %patch181 -p1 -b .rh1416304
+%patch182 -p1 -b .CVE-2017-3142+3143
 
 # Override upstream builtin keys
 cp -fp %{SOURCE29} bind.keys
@@ -1128,6 +1131,9 @@ rm -rf ${RPM_BUILD_ROOT}
 %endif
 
 %changelog
+* Thu Jun 29 2017 Petr Menšík <pemensik@redhat.com> - 32:9.9.4-51
+- Fix CVE-2017-3142 and CVE-2017-3143
+
 * Mon May 22 2017 Petr Menšík <pemensik@redhat.com> - 32:9.9.4-50
 - Update root servers and trust anchor (#1452635)