QAT_Engine icon indicating copy to clipboard operation
QAT_Engine copied to clipboard

division by zero when qat_get_sha3_data_size returns zero

Open ColinIanKing opened this issue 2 years ago • 3 comments

In function qat_sha3_update() in source qat_hw_sha3.c there is a division by zero on the corner case where qat_get_sha3_data_size() returns zero when using an unsupported hash algorithm:

  1. The function can return 0:

static int qat_get_sha3_data_size(int nid)
{
    switch (nid) {
    case NID_sha3_224:
        return QAT_SHA3_224_OFFLOAD_THRESHOLD;
    case NID_sha3_256:
        return QAT_SHA3_256_OFFLOAD_THRESHOLD;
    case NID_sha3_384:
        return QAT_SHA3_384_OFFLOAD_THRESHOLD;
    case NID_sha3_512:
        return QAT_SHA3_512_OFFLOAD_THRESHOLD;
    default:
        WARN("Unsupported Hash Algorithm\n");
        return 0;
    }
}
  1. The data_size variable can potentially be assigned zero from the call to the qat_get_sha3_data_size() call:
#ifdef QAT_OPENSSL_PROVIDER
    data_size = qat_get_sha3_data_size(ctx->md_type);
#else
    data_size = qat_get_sha3_data_size(EVP_MD_CTX_type(ctx));
#endif

    n = sha3_ctx->num;

#ifndef QAT_OPENSSL_PROVIDER
# ifndef ENABLE_QAT_SMALL_PKT_OFFLOAD
    if (sha3_ctx->sw_offload ||
       (len <= CRYPTO_SMALL_PACKET_OFFLOAD_THRESHOLD_DEFAULT)) {
        DEBUG("Packet size < 2048, Using OpenSSL SW\n");
        sha3_ctx->sw_offload = 1;
        return EVP_MD_meth_get_update(GET_SW_SHA3_DIGEST(ctx))
                  (ctx, in, len);
    }
# endif
#endif

    /* Packets left from previous process */
    if (n != 0) {
        p = (unsigned char *)sha3_ctx->data;

        /* Offload threshold met */
        if (len >= data_size || len + n >= data_size) {
            /* Use part of new packet filling the packet buffer */
            memcpy(p + n, data, data_size - n);
            qat_hw_sha3_offload(ctx, p, data_size, CPA_CY_SYM_PACKET_TYPE_PARTIAL);

            /* The data left of new input */
            n = data_size - n;
            data += n;
            len -= n;
            sha3_ctx->num = 0;
            /*
             * We use memset rather than OPENSSL_cleanse() here deliberately.
             * Using OPENSSL_cleanse() here could be a performance issue. It
             * will get properly cleansed on finalisation so this isn't a
             * security problem.
             */
            memset(p, 0, data_size); /* keep it zeroed */
        } else {
            /* Append the new packets to buffer */
            memcpy(p + n, data, len);
            sha3_ctx->num += (unsigned int)len;
            return 1;
        }
    }

    n = len / data_size;

The assignment to n may be dividing by a zero data_size value.

ColinIanKing avatar Jul 18 '23 11:07 ColinIanKing

Let me check on this and fix it

Yogaraj-Alamenda avatar Jul 27 '23 17:07 Yogaraj-Alamenda