Commit message: Apply CVE fixes for X509 parsing

Apply patches developed by Sze Yiu which correct a vulnerability in
X509 parsing.  See CVE-2018-16150 and CVE-2018-16149 for more info.
CVE: CVE-2018-16253
CWE: CWE-347
Vulnerability description: In sig_verify() in x509.c in axTLS version 2.1.3 and before, the PKCS#1 v1.5 signature verification does not properly verify the ASN.1 metadata. Consequently, a remote attacker can forge signatures when small public exponents are being used, which could lead to impersonation through fake X.509 certificates. This is an even more permissive variant of CVE-2006-4790 and CVE-2014-1568.

Project: axtls-8266

static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, uint8_t sig_type,
         bigint *modulus, bigint *pub_exp)
 {
    int i;
     bigint *decrypted_bi, *dat_bi;
     bigint *bir = NULL;
     uint8_t *block = (uint8_t *)malloc(sig_len);
 
    const uint8_t *sig_prefix = NULL;
    uint8_t sig_prefix_size = 0, hash_len = 0;
    /* adjust our expections */
    switch (sig_type)
    {
        case SIG_TYPE_MD5:
            sig_prefix = sig_prefix_md5;
            sig_prefix_size = sizeof(sig_prefix_md5);
        break;
        case SIG_TYPE_SHA1:
            sig_prefix = sig_prefix_sha1;
            sig_prefix_size = sizeof(sig_prefix_sha1);
        break;
        case SIG_TYPE_SHA256:
            sig_prefix = sig_prefix_sha256;
            sig_prefix_size = sizeof(sig_prefix_sha256);
        break;
        case SIG_TYPE_SHA384:
            sig_prefix = sig_prefix_sha384;
            sig_prefix_size = sizeof(sig_prefix_sha384);
        break;
        case SIG_TYPE_SHA512:
            sig_prefix = sig_prefix_sha512;
            sig_prefix_size = sizeof(sig_prefix_sha512);
        break;
    }
    if (sig_prefix)
        hash_len = sig_prefix[sig_prefix_size - 1];

    /* check length (#A) */
    if (sig_len < 2 + 8 + 1 + sig_prefix_size + hash_len)
        goto err;

     /* decrypt */
     dat_bi = bi_import(ctx, sig, sig_len);
     ctx->mod_offset = BIGINT_M_OFFSET;

    /* convert to a normal block */
    decrypted_bi = bi_mod_power2(ctx, dat_bi, modulus, pub_exp);

     bi_export(ctx, decrypted_bi, block, sig_len);
     ctx->mod_offset = BIGINT_M_OFFSET;
 
    /* check the first 2 bytes */
    if (block[0] != 0 || block[1] != 1)
        goto err;
 
    /* check the padding */
    i = 2; /* start at the first padding byte */
    while (i < sig_len - 1 - sig_prefix_size - hash_len)
    { /* together with (#A), we require at least 8 bytes of padding */
        if (block[i++] != 0xFF)
            goto err;
     }

    /* check end of padding */
    if (block[i++] != 0)
        goto err;

    /* check the ASN.1 metadata */
    if (memcmp_P(block+i, sig_prefix, sig_prefix_size))
        goto err;

    /* now we can get the hash we need */
    bir = bi_import(ctx, block + i + sig_prefix_size, hash_len);

err:
     free(block);
     /* save a few bytes of memory */
     bi_clear_cache(ctx);
    return bir;
}

Project: axtls-8266
File: x509.c

int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert, 
        int *pathLenConstraint) 
{
    int ret = X509_OK, i = 0;
    bigint *cert_sig;
    X509_CTX *next_cert = NULL;
    BI_CTX *ctx = NULL;
    bigint *mod = NULL, *expn = NULL;
    int match_ca_cert = 0;
    struct timeval tv;
    uint8_t is_self_signed = 0;

    if (cert == NULL)
    {
        ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
        goto end_verify;
    }

    /* a self-signed certificate that is not in the CA store - use this 
       to check the signature */
    if (asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0)
    {
        is_self_signed = 1;
        ctx = cert->rsa_ctx->bi_ctx;
        mod = cert->rsa_ctx->m;
        expn = cert->rsa_ctx->e;
    }

    gettimeofday(&tv, NULL);

    /* check the not before date */
    if (tv.tv_sec < cert->not_before)
    {
        ret = X509_VFY_ERROR_NOT_YET_VALID;
        goto end_verify;
    }

    /* check the not after date */
    if (tv.tv_sec > cert->not_after)
    {
        ret = X509_VFY_ERROR_EXPIRED;
        goto end_verify;
    }

    if (cert->basic_constraint_present)
    {
        /* If the cA boolean is not asserted,
           then the keyCertSign bit in the key usage extension MUST NOT be
           asserted. */
        if (!cert->basic_constraint_cA &&
                IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_CERT_SIGN))
        {
            ret = X509_VFY_ERROR_BASIC_CONSTRAINT;
            goto end_verify;
        }

        /* The pathLenConstraint field is meaningful only if the cA boolean is
           asserted and the key usage extension, if present, asserts the
           keyCertSign bit.  In this case, it gives the maximum number of 
           non-self-issued intermediate certificates that may follow this 
           certificate in a valid certification path. */
        if (cert->basic_constraint_cA &&
            (!cert->key_usage_present || 
                IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_CERT_SIGN)) &&
            (cert->basic_constraint_pathLenConstraint+1) < *pathLenConstraint)
        {
            ret = X509_VFY_ERROR_BASIC_CONSTRAINT;
            goto end_verify;
        }
    }

    next_cert = cert->next;

    /* last cert in the chain - look for a trusted cert */
    if (next_cert == NULL)
    {
       if (ca_cert_ctx != NULL) 
       {
            /* go thru the CA store */
            while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
            {
                /* the extension is present but the cA boolean is not 
                   asserted, then the certified public key MUST NOT be used 
                   to verify certificate signatures. */
                if (cert->basic_constraint_present && 
                        !ca_cert_ctx->cert[i]->basic_constraint_cA)
                    continue;
                        
                if (asn1_compare_dn(cert->ca_cert_dn,
                                            ca_cert_ctx->cert[i]->cert_dn) == 0)
                {
                    /* use this CA certificate for signature verification */
                    match_ca_cert = true;
                    ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
                    mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
                    expn = ca_cert_ctx->cert[i]->rsa_ctx->e;


                    break;
                }

                i++;
            }
        }

        /* couldn't find a trusted cert (& let self-signed errors 
           be returned) */
        if (!match_ca_cert && !is_self_signed)
        {
            ret = X509_VFY_ERROR_NO_TRUSTED_CERT;       
            goto end_verify;
        }
    }
    else if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn) != 0)
    {
        /* check the chain */
        ret = X509_VFY_ERROR_INVALID_CHAIN;
        goto end_verify;
    }
    else /* use the next certificate in the chain for signature verify */
    {
        ctx = next_cert->rsa_ctx->bi_ctx;
        mod = next_cert->rsa_ctx->m;
        expn = next_cert->rsa_ctx->e;
    }

    /* cert is self signed */
    if (!match_ca_cert && is_self_signed)
    {
        ret = X509_VFY_ERROR_SELF_SIGNED;
        goto end_verify;
     }
 
     /* check the signature */
    cert_sig = sig_verify(ctx, cert->signature, cert->sig_len, cert->sig_type,
                         bi_clone(ctx, mod), bi_clone(ctx, expn));
 
     if (cert_sig && cert->digest)
    {
        if (bi_compare(cert_sig, cert->digest) != 0)
            ret = X509_VFY_ERROR_BAD_SIGNATURE;


        bi_free(ctx, cert_sig);
    }
    else
    {
        ret = X509_VFY_ERROR_BAD_SIGNATURE;
    }

    bi_clear_cache(ctx);

    if (ret)
        goto end_verify;

    /* go down the certificate chain using recursion. */
    if (next_cert != NULL)
    {
        (*pathLenConstraint)++; /* don't include last certificate */
        ret = x509_verify(ca_cert_ctx, next_cert, pathLenConstraint);
    }

end_verify:
    return ret;
}