Ejemplo n.º 1
0
static int asn1_find_oid(const uint8_t* cert, int* offset, 
                    const uint8_t* oid, int oid_length)
{
    int seqlen;
    if ((seqlen = asn1_next_obj(cert, offset, ASN1_SEQUENCE))> 0)
    {
        int end = *offset + seqlen;

        while (*offset < end)
        {
            int type = cert[(*offset)++];
            int length = get_asn1_length(cert, offset);
            int noffset = *offset + length;

            if (type == ASN1_SEQUENCE)
            {
                type = cert[(*offset)++];
                length = get_asn1_length(cert, offset);

                if (type == ASN1_OID && length == oid_length && 
                              memcmp(cert + *offset, oid, oid_length) == 0)
                {
                    *offset += oid_length;
                    return 1;
                }
            }

            *offset = noffset;
        }
    }

    return 0;
}
Ejemplo n.º 2
0
/**
 * Skip the ASN1.1 object type and its length. Get ready to read the object's
 * data.
 */
int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type)
{
    if (buf[*offset] != obj_type)
        return X509_NOT_OK;
    (*offset)++;
    return get_asn1_length(buf, offset);
}
Ejemplo n.º 3
0
/**
 * Read the signature type of the certificate. We only support RSA-MD5 and
 * RSA-SHA1 signature types.
 */
int asn1_signature_type(const uint8_t *cert, 
                                int *offset, X509_CTX *x509_ctx)
{
    int ret = X509_NOT_OK, len;

    if (cert[(*offset)++] != ASN1_OID)
        goto end_check_sig;

    len = get_asn1_length(cert, offset);

    if (len == 5 && memcmp(sig_iis6_oid, &cert[*offset], 
                                    SIG_IIS6_OID_SIZE) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA1;
    }
    else
    {
        if (memcmp(sig_oid_prefix, &cert[*offset], SIG_OID_PREFIX_SIZE))
            goto end_check_sig;     /* unrecognised cert type */

        x509_ctx->sig_type = cert[*offset + SIG_OID_PREFIX_SIZE];
    }

    *offset += len;
    asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
    ret = X509_OK;

end_check_sig:
    return ret;
}
Ejemplo n.º 4
0
/**
 * Get the time of a certificate. Ignore hours/minutes/seconds.
 */
static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
{
    int ret = X509_NOT_OK, len, t_offset;
    struct tm tm;

    if (buf[(*offset)++] != ASN1_UTC_TIME)
        goto end_utc_time;

    len = get_asn1_length(buf, offset);
    t_offset = *offset;

    memset(&tm, 0, sizeof(struct tm));
    tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');

    if (tm.tm_year <= 50)    /* 1951-2050 thing */
    {
        tm.tm_year += 100;
    }

    tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
    tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
    *t = mktime(&tm);
    *offset += len;
    ret = X509_OK;

end_utc_time:
    return ret;
}
Ejemplo n.º 5
0
/**
 * Read the signature type of the certificate. We only support RSA-MD5 and
 * RSA-SHA1 signature types.
 */
int asn1_signature_type(const uint8_t *cert, 
                                int *offset, X509_CTX *x509_ctx)
{
    int ret = X509_NOT_OK, len;

    if (cert[(*offset)++] != ASN1_OID)
        goto end_check_sig;

    len = get_asn1_length(cert, offset);

    if (len == sizeof(sig_sha1WithRSAEncrypt) && 
            memcmp(sig_sha1WithRSAEncrypt, &cert[*offset], 
                                    sizeof(sig_sha1WithRSAEncrypt)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA1;
    }
    else if (len == sizeof(sig_sha256) && 
            memcmp(sig_sha256, &cert[*offset], 
                                    sizeof(sig_sha256)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA256;
    }
    else if (len == sizeof(sig_sha384) && 
            memcmp(sig_sha384, &cert[*offset], 
                                    sizeof(sig_sha384)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA384;
    }
    else if (len == sizeof(sig_sha512) && 
            memcmp(sig_sha512, &cert[*offset], 
                                    sizeof(sig_sha512)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA512;
    }
    else
    {
        if (memcmp(sig_oid_prefix, &cert[*offset], sizeof(sig_oid_prefix)))
        {
#ifdef CONFIG_SSL_FULL_MODE
            int i;
            printf("invalid digest: ");

            for (i = 0; i < len; i++)
                printf("%02x ", cert[*offset + i]);

            printf("\n");
#endif
            goto end_check_sig;     /* unrecognised cert type */
        }

        x509_ctx->sig_type = cert[*offset + sizeof(sig_oid_prefix)];
    }

    *offset += len;
    asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
    ret = X509_OK;

end_check_sig:
    return ret;
}
Ejemplo n.º 6
0
/**
 * Skip over an ASN.1 object type completely. Get ready to read the next
 * object.
 */
int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
{
    int len;
    if (buf[*offset] != obj_type)
        return X509_NOT_OK;
    (*offset)++;
    len = get_asn1_length(buf, offset);
    *offset += len;
    return 0;
}
Ejemplo n.º 7
0
/**
 * Read the signature type of the certificate. We only support RSA-MD5 and
 * RSA-SHA1 signature types.
 */
int ICACHE_FLASH_ATTR asn1_signature_type(const uint8_t *cert, 
                                int *offset, X509_CTX *x509_ctx)
{
    int ret = X509_NOT_OK, len;

    if (cert[(*offset)++] != ASN1_OID)
        goto end_check_sig;

    len = get_asn1_length(cert, offset);

    if (len == sizeof(sig_sha1WithRSAEncrypt) && 
            memcmp(sig_sha1WithRSAEncrypt, &cert[*offset], 
                                    sizeof(sig_sha1WithRSAEncrypt)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA1;
    }
    else if (len == sizeof(sig_sha256) && 
            memcmp(sig_sha256, &cert[*offset], 
                                    sizeof(sig_sha256)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA256;
    }
    else if (len == sizeof(sig_sha384) && 
            memcmp(sig_sha384, &cert[*offset], 
                                    sizeof(sig_sha384)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA384;
    }
    else if (len == sizeof(sig_sha512) && 
            memcmp(sig_sha512, &cert[*offset], 
                                    sizeof(sig_sha512)) == 0)
    {
        x509_ctx->sig_type = SIG_TYPE_SHA512;
    }
    else
    {
        if (memcmp(sig_oid_prefix, &cert[*offset], sizeof(sig_oid_prefix)))
            goto end_check_sig;     /* unrecognised cert type */

        x509_ctx->sig_type = cert[*offset + sizeof(sig_oid_prefix)];
    }

    *offset += len;
    asn1_skip_obj(cert, offset, ASN1_NULL); /* if it's there */
    ret = X509_OK;

end_check_sig:
    return ret;
}
Ejemplo n.º 8
0
/**
 * Read the signature of the certificate.
 */
int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
    int ret = X509_NOT_OK;

    if (cert[(*offset)++] != ASN1_BIT_STRING)
        goto end_sig;

    x509_ctx->sig_len = get_asn1_length(cert, offset)-1;
    (*offset)++;            /* ignore bit string padding bits */
    x509_ctx->signature = (uint8_t *)malloc(x509_ctx->sig_len);
    memcpy(x509_ctx->signature, &cert[*offset], x509_ctx->sig_len);
    *offset += x509_ctx->sig_len;
    ret = X509_OK;

end_sig:
    return ret;
}
Ejemplo n.º 9
0
/**
 * Retrieve the signature from a certificate.
 */
static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
{
    int offset = 0;
    const uint8_t *ptr = NULL;

    if (asn1_next_obj(asn1_sig, &offset, ASN1_SEQUENCE) < 0 ||
            asn1_skip_obj(asn1_sig, &offset, ASN1_SEQUENCE))
        goto end_get_sig;

    if (asn1_sig[offset++] != ASN1_OCTET_STRING)
        goto end_get_sig;
    *len = get_asn1_length(asn1_sig, &offset);
    ptr = &asn1_sig[offset];          /* all ok */

end_get_sig:
    return ptr;
}
Ejemplo n.º 10
0
    /* Saves a few bytes of memory */
    bi_clear_cache(bi_ctx);
#endif
    ret = X509_OK;
end_cert:
    if (len)
    {
        *len = cert_size;
    }

    if (ret)
    {
#ifdef CONFIG_SSL_FULL_MODE
        char buff[64];
        printf("Error: Invalid X509 ASN.1 file (%s)\n",
                        x509_display_error(ret, buff));
#endif
        x509_free(x509_ctx);
        *ctx = NULL;
    }

    return ret;
}

#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
static int x509_v3_subject_alt_name(const uint8_t *cert, int offset, 
        X509_CTX *x509_ctx)
{
    if ((offset = asn1_is_subject_alt_name(cert, offset)) > 0)
    {
        x509_ctx->subject_alt_name_present = true;
        x509_ctx->subject_alt_name_is_critical = 
                        asn1_is_critical_ext(cert, &offset);

        if (asn1_next_obj(cert, &offset, ASN1_OCTET_STRING) > 0)
        {
            int altlen;

            if ((altlen = asn1_next_obj(cert, &offset, ASN1_SEQUENCE)) > 0)
            {
                int endalt = offset + altlen;
                int totalnames = 0;

                while (offset < endalt)
                {
                    int type = cert[offset++];
                    int dnslen = get_asn1_length(cert, &offset);

                    if (type == ASN1_CONTEXT_DNSNAME)
                    {
                        x509_ctx->subject_alt_dnsnames = (char**)
                                realloc(x509_ctx->subject_alt_dnsnames, 
                                   (totalnames + 2) * sizeof(char*));
                        x509_ctx->subject_alt_dnsnames[totalnames] = 
                                (char*)malloc(dnslen + 1);
                        x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
                        memcpy(x509_ctx->subject_alt_dnsnames[totalnames], 
                                cert + offset, dnslen);
                        x509_ctx->subject_alt_dnsnames[totalnames][dnslen] = 0;
                        totalnames++;
                    }

                    offset += dnslen;
                }
            }
        }
    }

    return X509_OK;
}
Ejemplo n.º 11
0
/**
 * Obtain an ASN.1 printable string type.
 */
static int asn1_get_printable_str(const uint8_t *buf, int *offset, char **str)
{
    int len = X509_NOT_OK;
    int string_type = buf[*offset]; /* GBG */
    
    /* some certs have this awful crud in them for some reason */
    if (string_type != ASN1_PRINTABLE_STR &&  
        string_type != ASN1_TELETEX_STR   &&  
        string_type != ASN1_IA5_STR       &&  
        string_type != ASN1_UNICODE_STR   &&
        string_type != ASN1_UTF8_STR      &&
        string_type != ASN1_UNIVERSAL_STR)
        goto end_pnt_str;

        (*offset)++;
        len = get_asn1_length(buf, offset);

        if (string_type == ASN1_UNICODE_STR)
        {
            int i;
            *str = (char *)malloc(len/2+1);     /* allow for null */

            for (i = 0; i < len; i += 2)
                (*str)[i/2] = buf[*offset + i + 1];

            (*str)[len/2] = 0;                  /* null terminate */
        }
        else
        {
            *str = (char *)malloc(len+1);       /* allow for null */
            memcpy(*str, &buf[*offset], len);
            (*str)[len] = 0;                    /* null terminate */
        }

        *offset += len;

end_pnt_str:
    return len;
}
Ejemplo n.º 12
0
/**
 * Get the time of a certificate. Ignore hours/minutes/seconds.
 */
static int asn1_get_utc_time(const uint8_t *buf, int *offset, SSL_DateTime *t)
{
    int ret = X509_NOT_OK, len, t_offset;
    uint8_t time_encoding;
    
    memset(t, 0, sizeof(*t));
    time_encoding = buf[(*offset)++];
    if (time_encoding != ASN1_UTC_TIME && time_encoding != ASN1_GENERALIZED_TIME) /* GBG */
        goto end_utc_time;
    len = get_asn1_length(buf, offset);
    t_offset = *offset;

    if (time_encoding == ASN1_UTC_TIME) {
        t->year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');

        if (t->year <= 50)    /* 1951-2050 thing */
        {
            t->year += 100;
        }
        t->year += 1900;
        t_offset += 2;
    } else {
        t->year = (buf[t_offset  ] - '0')*1000 +
                  (buf[t_offset+1] - '0')*100  + 
                  (buf[t_offset+2] - '0')*10   + 
                  (buf[t_offset+3] - '0');
        t_offset += 4;
    }

    t->month = (buf[t_offset  ] - '0')*10 + (buf[t_offset+1] - '0');
    t->day   = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0');
    *offset += len;
    ret = X509_OK;

end_utc_time:
    return ret;
}
Ejemplo n.º 13
0
Archivo: asn1.c Proyecto: yingted/axtls
/**
 * Get the time of a certificate. Ignore hours/minutes/seconds.
 */
static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
{
    int ret = X509_NOT_OK, len, t_offset, abs_year;
    struct tm tm;

    /* see http://tools.ietf.org/html/rfc5280#section-4.1.2.5 */
    if (buf[*offset] == ASN1_UTC_TIME)
    {
        (*offset)++;

        len = get_asn1_length(buf, offset);
        t_offset = *offset;

        memset(&tm, 0, sizeof(struct tm));
        tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');

        if (tm.tm_year <= 50)    /* 1951-2050 thing */
        {
            tm.tm_year += 100;
        }

        tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
        tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
        *t = mktime(&tm);
        *offset += len;
        ret = X509_OK;
    }
    else if (buf[*offset] == ASN1_GENERALIZED_TIME)
    {
        (*offset)++;

        len = get_asn1_length(buf, offset);
        t_offset = *offset;

        memset(&tm, 0, sizeof(struct tm));
        abs_year = ((buf[t_offset] - '0')*1000 +
                (buf[t_offset+1] - '0')*100 + (buf[t_offset+2] - '0')*10 +
                (buf[t_offset+3] - '0'));

        if (abs_year <= 1901)
        {
          tm.tm_year = 1;
          tm.tm_mon = 0;
          tm.tm_mday = 1;
        }
        else
        {
          tm.tm_year = abs_year - 1900;
          tm.tm_mon = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0') - 1;
          tm.tm_mday = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
          tm.tm_hour = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
          tm.tm_min = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
          tm.tm_sec = (buf[t_offset+12] - '0')*10 + (buf[t_offset+13] - '0');
          *t = mktime(&tm);
        }

        *offset += len;
        ret = X509_OK;
    }

    return ret;
}
Ejemplo n.º 14
0
/**
 * Construct a new x509 object.
 * @return 0 if ok. < 0 if there was a problem.
 */
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
{
    int begin_tbs, end_tbs;
    int ret = X509_NOT_OK, offset = 0, cert_size = 0;
    X509_CTX *x509_ctx;
    BI_CTX *bi_ctx;

    *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
    x509_ctx = *ctx;

    /* get the certificate size */
    asn1_skip_obj(cert, &cert_size, ASN1_SEQUENCE);

    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    begin_tbs = offset;         /* start of the tbs */
    end_tbs = begin_tbs;        /* work out the end of the tbs */
    asn1_skip_obj(cert, &end_tbs, ASN1_SEQUENCE);

    if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
    {
        if (asn1_version(cert, &offset, x509_ctx))
            goto end_cert;
    }

    if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */
            asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
        goto end_cert;

    /* make sure the signature is ok */
    if (asn1_signature_type(cert, &offset, x509_ctx))
    {
        ret = X509_VFY_ERROR_UNSUPPORTED_DIGEST;
        goto end_cert;
    }

    if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
            asn1_validity(cert, &offset, x509_ctx) ||
            asn1_name(cert, &offset, x509_ctx->cert_dn) ||
            asn1_public_key(cert, &offset, x509_ctx))
    {
        goto end_cert;
    }

    bi_ctx = x509_ctx->rsa_ctx->bi_ctx;

    x509_ctx->fingerprint = malloc(SHA1_SIZE);
    SHA1_CTX sha_fp_ctx;
    SHA1_Init(&sha_fp_ctx);
    SHA1_Update(&sha_fp_ctx, &cert[0], cert_size);
    SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx);

#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
    /* use the appropriate signature algorithm (SHA1/MD5/MD2) */
    if (x509_ctx->sig_type == SIG_TYPE_MD5)
    {
        MD5_CTX md5_ctx;
        uint8_t md5_dgst[MD5_SIZE];
        MD5_Init(&md5_ctx);
        MD5_Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        MD5_Final(md5_dgst, &md5_ctx);
        x509_ctx->digest = bi_import(bi_ctx, md5_dgst, MD5_SIZE);
    }
    else if (x509_ctx->sig_type == SIG_TYPE_SHA1)
    {
        SHA1_CTX sha_ctx;
        uint8_t sha_dgst[SHA1_SIZE];
        SHA1_Init(&sha_ctx);
        SHA1_Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        SHA1_Final(sha_dgst, &sha_ctx);
        x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE);
    }
    else if (x509_ctx->sig_type == SIG_TYPE_MD2)
    {
        MD2_CTX md2_ctx;
        uint8_t md2_dgst[MD2_SIZE];
        MD2_Init(&md2_ctx);
        MD2_Update(&md2_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
        MD2_Final(md2_dgst, &md2_ctx);
        x509_ctx->digest = bi_import(bi_ctx, md2_dgst, MD2_SIZE);
    }

    if (cert[offset] == ASN1_V3_DATA)
    {
        int suboffset;

        ++offset;
        get_asn1_length(cert, &offset);

        if ((suboffset = asn1_find_subjectaltname(cert, offset)) > 0)
        {
            if (asn1_next_obj(cert, &suboffset, ASN1_OCTET_STRING) > 0)
            {
                int altlen;

                if ((altlen = asn1_next_obj(cert,
                                            &suboffset, ASN1_SEQUENCE)) > 0)
                {
                    int endalt = suboffset + altlen;
                    int totalnames = 0;

                    while (suboffset < endalt)
                    {
                        int type = cert[suboffset++];
                        int dnslen = get_asn1_length(cert, &suboffset);

                        if (type == ASN1_CONTEXT_DNSNAME)
                        {
                            x509_ctx->subject_alt_dnsnames = (char**)
                                                             realloc(x509_ctx->subject_alt_dnsnames,
                                                                     (totalnames + 2) * sizeof(char*));
                            x509_ctx->subject_alt_dnsnames[totalnames] =
                                (char*)malloc(dnslen + 1);
                            x509_ctx->subject_alt_dnsnames[totalnames+1] = NULL;
                            memcpy(x509_ctx->subject_alt_dnsnames[totalnames],
                                   cert + suboffset, dnslen);
                            x509_ctx->subject_alt_dnsnames[
                                totalnames][dnslen] = 0;
                            ++totalnames;
                        }

                        suboffset += dnslen;
                    }
                }
            }
        }
    }

    offset = end_tbs;   /* skip the rest of v3 data */
    if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) ||
            asn1_signature(cert, &offset, x509_ctx))
        goto end_cert;
#endif
    ret = X509_OK;
end_cert:
    if (len)
    {
        *len = cert_size;
    }

    if (ret)
    {
#ifdef CONFIG_SSL_FULL_MODE
        printf("Error: Invalid X509 ASN.1 file (%s)\n",
               x509_display_error(ret));
#endif
        x509_free(x509_ctx);
        *ctx = NULL;
    }

    return ret;
}