Commit 77196bef authored by Michał Kępień's avatar Michał Kępień

Merge branch '2037-confidential-issue-v9_16' into 'security-v9_16'

[CVE-2020-8623]: Fix crash in pk11_numbits() with crafted packet when native-pkcs11 is used (v9.16)

See merge request isc-private/bind9!199
parents d5b42ddd e3bd627e
......@@ -10,6 +10,12 @@
system, but the Duplicate Address Detection (DAD)
mechanism had not yet finished. [GL #2038]
5480. [security] When BIND 9 was compiled with native PKCS#11 support, it
was possible to trigger an assertion failure in code
determining the number of bits in the PKCS#11 RSA public
key with a specially crafted packet. (CVE-2020-8623)
[GL #2037]
5479. [security] named could crash in certain query resolution scenarios
where QNAME minimization and forwarding were both
enabled. (CVE-2020-8621) [GL #1997]
......
......@@ -36,6 +36,14 @@ Security Fixes
ISC would like to thank Dave Feldman, Jeff Warren, and Joel Cunningham
of Oracle for bringing this vulnerability to our attention. [GL #2028]
- When BIND 9 was compiled with native PKCS#11 support, it was possible
to trigger an assertion failure in code determining the number of bits
in the PKCS#11 RSA public key with a specially crafted packet. This
was disclosed in CVE-2020-8623.
ISC would like to thank Lyu Chiy for bringing this vulnerability to
our attention. [GL #2037]
Known Issues
~~~~~~~~~~~~
......
......@@ -294,6 +294,7 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
key->key_alg == DST_ALG_NSEC3RSASHA1 ||
key->key_alg == DST_ALG_RSASHA256 ||
key->key_alg == DST_ALG_RSASHA512);
REQUIRE(maxbits <= RSA_MAX_PUBEXP_BITS);
/*
* Reject incorrect RSA key lengths.
......@@ -336,6 +337,7 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
for (attr = pk11_attribute_first(rsa); attr != NULL;
attr = pk11_attribute_next(rsa, attr))
{
switch (attr->type) {
case CKA_MODULUS:
INSIST(keyTemplate[5].type == attr->type);
......@@ -352,13 +354,16 @@ pkcs11rsa_createctx_verify(dst_key_t *key, unsigned int maxbits,
memmove(keyTemplate[6].pValue, attr->pValue,
attr->ulValueLen);
keyTemplate[6].ulValueLen = attr->ulValueLen;
if (pk11_numbits(attr->pValue, attr->ulValueLen) >
maxbits &&
maxbits != 0) {
unsigned int bits;
ret = pk11_numbits(attr->pValue, attr->ulValueLen,
&bits);
if (ret != ISC_R_SUCCESS ||
(bits > maxbits && maxbits != 0)) {
DST_RET(DST_R_VERIFYFAILURE);
}
break;
}
}
pk11_ctx->object = CK_INVALID_HANDLE;
pk11_ctx->ontoken = false;
PK11_RET(pkcs_C_CreateObject,
......@@ -959,14 +964,17 @@ pkcs11rsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
keyTemplate[5].ulValueLen = attr->ulValueLen;
break;
case CKA_PUBLIC_EXPONENT:
unsigned int bits;
INSIST(keyTemplate[6].type == attr->type);
keyTemplate[6].pValue = isc_mem_get(dctx->mctx,
attr->ulValueLen);
memmove(keyTemplate[6].pValue, attr->pValue,
attr->ulValueLen);
keyTemplate[6].ulValueLen = attr->ulValueLen;
if (pk11_numbits(attr->pValue, attr->ulValueLen) >
RSA_MAX_PUBEXP_BITS) {
ret = pk11_numbits(attr->pValue, attr->ulValueLen,
&bits);
if (ret != ISC_R_SUCCESS || bits > RSA_MAX_PUBEXP_BITS)
{
DST_RET(DST_R_VERIFYFAILURE);
}
break;
......@@ -1337,6 +1345,8 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
CK_BYTE *exponent = NULL, *modulus = NULL;
CK_ATTRIBUTE *attr;
unsigned int length;
unsigned int bits;
isc_result_t ret = ISC_R_SUCCESS;
isc_buffer_remainingregion(data, &r);
if (r.length == 0) {
......@@ -1353,9 +1363,7 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
if (e_bytes == 0) {
if (r.length < 2) {
isc_safe_memwipe(rsa, sizeof(*rsa));
isc_mem_put(key->mctx, rsa, sizeof(*rsa));
return (DST_R_INVALIDPUBLICKEY);
DST_RET(DST_R_INVALIDPUBLICKEY);
}
e_bytes = (*r.base) << 8;
isc_region_consume(&r, 1);
......@@ -1364,16 +1372,18 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
}
if (r.length < e_bytes) {
isc_safe_memwipe(rsa, sizeof(*rsa));
isc_mem_put(key->mctx, rsa, sizeof(*rsa));
return (DST_R_INVALIDPUBLICKEY);
DST_RET(DST_R_INVALIDPUBLICKEY);
}
exponent = r.base;
isc_region_consume(&r, e_bytes);
modulus = r.base;
mod_bytes = r.length;
key->key_size = pk11_numbits(modulus, mod_bytes);
ret = pk11_numbits(modulus, mod_bytes, &bits);
if (ret != ISC_R_SUCCESS) {
goto err;
}
key->key_size = bits;
isc_buffer_forward(data, length);
......@@ -1393,6 +1403,10 @@ pkcs11rsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
key->keydata.pkey = rsa;
return (ISC_R_SUCCESS);
err:
isc_safe_memwipe(rsa, sizeof(*rsa));
isc_mem_put(key->mctx, rsa, sizeof(*rsa));
return (ret);
}
static isc_result_t
......@@ -1566,6 +1580,7 @@ pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label,
pk11_object_t *pubrsa;
pk11_context_t *pk11_ctx = NULL;
isc_result_t ret;
unsigned int bits;
if (label == NULL) {
return (DST_R_NOENGINE);
......@@ -1644,7 +1659,11 @@ pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label,
attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
INSIST(attr != NULL);
key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits);
if (ret != ISC_R_SUCCESS) {
goto err;
}
key->key_size = bits;
return (ISC_R_SUCCESS);
......@@ -1736,6 +1755,7 @@ pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
CK_ATTRIBUTE *attr;
isc_mem_t *mctx = key->mctx;
const char *engine = NULL, *label = NULL;
unsigned int bits;
/* read private key file */
ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
......@@ -1873,12 +1893,20 @@ pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
INSIST(attr != NULL);
key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits);
if (ret != ISC_R_SUCCESS) {
goto err;
}
key->key_size = bits;
attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
INSIST(attr != NULL);
if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
{
ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits);
if (ret != ISC_R_SUCCESS) {
goto err;
}
if (bits > RSA_MAX_PUBEXP_BITS) {
DST_RET(ISC_R_RANGE);
}
......@@ -1913,6 +1941,7 @@ pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
pk11_context_t *pk11_ctx = NULL;
isc_result_t ret;
unsigned int i;
unsigned int bits;
UNUSED(pin);
......@@ -1998,14 +2027,22 @@ pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
INSIST(attr != NULL);
if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
{
ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits);
if (ret != ISC_R_SUCCESS) {
goto err;
}
if (bits > RSA_MAX_PUBEXP_BITS) {
DST_RET(ISC_R_RANGE);
}
attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
INSIST(attr != NULL);
key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);
ret = pk11_numbits(attr->pValue, attr->ulValueLen, &bits);
if (ret != ISC_R_SUCCESS) {
goto err;
}
key->key_size = bits;
pk11_return_session(pk11_ctx);
isc_safe_memwipe(pk11_ctx, sizeof(*pk11_ctx));
......
......@@ -30,8 +30,8 @@ pk11_mem_put(void *ptr, size_t size);
CK_SLOT_ID
pk11_get_best_token(pk11_optype_t optype);
unsigned int
pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt);
isc_result_t
pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt, unsigned int *bits);
CK_ATTRIBUTE *
pk11_attribute_first(const pk11_object_t *obj);
......
......@@ -654,13 +654,14 @@ pk11_get_best_token(pk11_optype_t optype) {
return (token->slotid);
}
unsigned int
pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) {
isc_result_t
pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt, unsigned int *bits) {
unsigned int bitcnt, i;
CK_BYTE top;
if (bytecnt == 0) {
return (0);
*bits = 0;
return (ISC_R_SUCCESS);
}
bitcnt = bytecnt * 8;
for (i = 0; i < bytecnt; i++) {
......@@ -670,33 +671,40 @@ pk11_numbits(CK_BYTE_PTR data, unsigned int bytecnt) {
continue;
}
if (top & 0x80) {
return (bitcnt);
*bits = bitcnt;
return (ISC_R_SUCCESS);
}
if (top & 0x40) {
return (bitcnt - 1);
*bits = bitcnt - 1;
return (ISC_R_SUCCESS);
}
if (top & 0x20) {
return (bitcnt - 2);
*bits = bitcnt - 2;
return (ISC_R_SUCCESS);
}
if (top & 0x10) {
return (bitcnt - 3);
*bits = bitcnt - 3;
return (ISC_R_SUCCESS);
}
if (top & 0x08) {
return (bitcnt - 4);
*bits = bitcnt - 4;
return (ISC_R_SUCCESS);
}
if (top & 0x04) {
return (bitcnt - 5);
*bits = bitcnt - 5;
return (ISC_R_SUCCESS);
}
if (top & 0x02) {
return (bitcnt - 6);
*bits = bitcnt - 6;
return (ISC_R_SUCCESS);
}
if (top & 0x01) {
return (bitcnt - 7);
*bits = bitcnt - 7;
return (ISC_R_SUCCESS);
}
break;
}
INSIST(0);
ISC_UNREACHABLE();
return (ISC_R_RANGE);
}
CK_ATTRIBUTE *
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment