示例#1
0
/**
 * Read the modulus and public exponent of a certificate.
 */
int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
    int ret = X509_NOT_OK, mod_len, pub_len;
    uint8_t *modulus = NULL, *pub_exp = NULL;

    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
            asn1_skip_obj(cert, offset, ASN1_SEQUENCE) ||
            asn1_next_obj(cert, offset, ASN1_BIT_STRING) < 0)
        goto end_pub_key;

    (*offset)++;        /* ignore the padding bit field */

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

    mod_len = asn1_get_int(cert, offset, &modulus);
    pub_len = asn1_get_int(cert, offset, &pub_exp);

    RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);

    free(modulus);
    free(pub_exp);
    ret = X509_OK;

end_pub_key:
    return ret;
}
示例#2
0
文件: p12.c 项目: Hamayama/Gauche
/*
 * Retrieve the salt/iteration details from a PBE block.
 */
static int get_pbe_params(uint8_t *buf, int *offset, 
        const uint8_t **salt, int *iterations)
{
    static const uint8_t pbeSH1RC4[] = /* pbeWithSHAAnd128BitRC4  */
            { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01 };

    int i, len;
    uint8_t *iter = NULL;
    int error_code = SSL_ERROR_NOT_SUPPORTED;

    /* Get the PBE type */
    if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
            (len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
        goto error;

    /* we expect pbeWithSHAAnd128BitRC4 (1.2.840.113549.1.12.1.1) 
       which is the only algorithm we support */
    if (len != sizeof(pbeSH1RC4) || 
                    memcmp(&buf[*offset], pbeSH1RC4, sizeof(pbeSH1RC4)))
    {
#ifdef CONFIG_SSL_FULL_MODE
        printf("Error: pkcs8/pkcs12 must use \"PBE-SHA1-RC4-128\"\n");
#endif
        goto error;
    }

    *offset += len;

    if (asn1_next_obj(buf, offset, ASN1_SEQUENCE) < 0 ||
            (len = asn1_next_obj(buf, offset, ASN1_OCTET_STRING)) < 0 || 
            len != 8)
        goto error;

    *salt = &buf[*offset];
    *offset += len;

    if ((len = asn1_get_big_int(buf, offset, &iter)) < 0)
        goto error;

    *iterations = 0;
    for (i = 0; i < len; i++)
    {
        (*iterations) <<= 8;
        (*iterations) += iter[i];
    }

    free(iter);
    error_code = SSL_OK;       /* got here - we are ok */

error:
    return error_code;
}
示例#3
0
文件: asn1.c 项目: 1deus/tmk_keyboard
/**
 * Get the subject name (or the issuer) of a certificate.
 */
int asn1_name(const uint8_t *cert, int *offset, char *dn[])
{
    int ret = X509_NOT_OK;
    int dn_type;
    char *tmp;

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

    while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
    {
        int i, found = 0;

        if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
               (dn_type = asn1_get_oid_x520(cert, offset)) < 0)
            goto end_name;

        tmp = NULL;

        if (asn1_get_printable_str(cert, offset, &tmp) < 0)
        {
            free(tmp);
            goto end_name;
        }

        /* find the distinguished named type */
        for (i = 0; i < X509_NUM_DN_TYPES; i++)
        {
            if (dn_type == g_dn_types[i])
            {
                if (dn[i] == NULL)
                {
                    dn[i] = tmp;
                    found = 1;
                    break;
                }
            }
        }

        if (found == 0) /* not found so get rid of it */
        {
            free(tmp);
        }
    }

    ret = X509_OK;
end_name:
    return ret;
}
示例#4
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;
}
示例#5
0
文件: x509.c 项目: slaff/axtls-8266
    /* 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;
}
示例#6
0
文件: x509.c 项目: slaff/axtls-8266
/**
 * Basic constraints - see https://tools.ietf.org/html/rfc5280#page-39
 */
static int x509_v3_basic_constraints(const uint8_t *cert, int offset, 
        X509_CTX *x509_ctx)
{
    int ret = X509_OK;
    int lenSeq = 0;

    if ((offset = asn1_is_basic_constraints(cert, offset)) == 0)
        goto end_contraints;

    x509_ctx->basic_constraint_present = true;
    x509_ctx->basic_constraint_is_critical = 
                    asn1_is_critical_ext(cert, &offset);

    /* Assign Defaults in case not specified
    basic_constraint_cA will already by zero by virtue of the calloc */
    x509_ctx->basic_constraint_cA = 0;
    /* basic_constraint_pathLenConstraint is unlimited by default. 
    10000 is just a large number (limits.h is not already included) */
    x509_ctx->basic_constraint_pathLenConstraint = 10000;
    
    if ((asn1_next_obj(cert, &offset, ASN1_OCTET_STRING) < 0) ||
            ((lenSeq = asn1_next_obj(cert, &offset, ASN1_SEQUENCE)) < 0))
    {
        ret = X509_NOT_OK;       
    }
    
    /* If the Sequence Length is greater than zero, 
    continue with the basic_constraint_cA */
    if ((lenSeq>0)&&(asn1_get_bool(cert, &offset, 
            &x509_ctx->basic_constraint_cA) < 0))
    {
        ret = X509_NOT_OK;
    }
    
    /* If the Sequence Length is greater than 3, it has more content than 
    the basic_constraint_cA bool, so grab the pathLenConstraint */
    if ((lenSeq>3) && (asn1_get_int(cert, &offset, 
            &x509_ctx->basic_constraint_pathLenConstraint) < 0))
    {
        ret = X509_NOT_OK;
    }

end_contraints:
    return ret;
}
示例#7
0
文件: p12.c 项目: Hamayama/Gauche
/*
 * Take a raw pkcs8 block and then decrypt it and turn it into a normal key.
 */
int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
{
    uint8_t *buf = ssl_obj->buf;
    int len, offset = 0;
    int iterations;
    int ret = SSL_NOT_OK;
    uint8_t *version = NULL;
    const uint8_t *salt;
    uint8_t *priv_key;
    int uni_pass_len;
    char *uni_pass = make_uni_pass(password, &uni_pass_len);

    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0)
    {
#ifdef CONFIG_SSL_FULL_MODE
        printf("Error: Invalid p8 ASN.1 file\n");
#endif
        goto error;
    }

    /* unencrypted key? */
    if (asn1_get_big_int(buf, &offset, &version) > 0 && *version == 0)
    {
        ret = p8_add_key(ssl_ctx, buf);
        goto error;
    }

    if (get_pbe_params(buf, &offset, &salt, &iterations) < 0)
        goto error;

    if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
        goto error;

    priv_key = &buf[offset];

    p8_decrypt(uni_pass, uni_pass_len, salt, 
                        iterations, priv_key, len, PKCS12_KEY_ID);
    ret = p8_add_key(ssl_ctx, priv_key);

error:
    free(version);
    free(uni_pass);
    return ret;
}
示例#8
0
文件: p12.c 项目: Lembed/uTLS
/*
 * Take the unencrypted pkcs8 and turn it into a private key
 */
static int p8_add_key(SSL_CTX *ssl_ctx, uint8_t *priv_key)
{
    uint8_t *buf = priv_key;
    int len, offset = 0;
    int ret = SSL_NOT_OK;

    /* Skip the preamble and go straight to the private key.
       We only support rsaEncryption (1.2.840.113549.1.1.1)  */
    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
        asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
        goto error;

    ret = asn1_get_private_key(&buf[offset], len, &ssl_ctx->rsa_ctx);

error:
    return ret;
}
示例#9
0
文件: x509.c 项目: cottsak/axtls-8266
/**
 * 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;
}
示例#10
0
/**
 * Get the components of a distinguished name 
 */
static int asn1_get_oid_x520(const uint8_t *buf, int *offset)
{
    int dn_type = 0;
    int len;

    if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
        goto end_oid;

    /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
       components we are interested in. */
    if (len == 3 && buf[*offset] == 0x55 && buf[*offset+1] == 0x04) { /* GBG */
        dn_type = buf[*offset+2];
    } 
    *offset += len;     /* skip over it */

end_oid:
    return dn_type;
}
示例#11
0
文件: x509.c 项目: slaff/axtls-8266
/*
 * Key usage - see https://tools.ietf.org/html/rfc5280#section-4.2.1.3
 */
static int x509_v3_key_usage(const uint8_t *cert, int offset, 
        X509_CTX *x509_ctx)
{
    int ret = X509_OK;

    if ((offset = asn1_is_key_usage(cert, offset)) == 0)
        goto end_key_usage;

    x509_ctx->key_usage_present = true;
    x509_ctx->key_usage_is_critical = asn1_is_critical_ext(cert, &offset);

    if (asn1_next_obj(cert, &offset, ASN1_OCTET_STRING) < 0 ||
            asn1_get_bit_string_as_int(cert, &offset, &x509_ctx->key_usage))
    {
        ret = X509_NOT_OK;       
    }

end_key_usage:
    return ret;
}
示例#12
0
/**
 * Read an integer value for ASN.1 data
 * Note: This function allocates memory which must be freed by the user.
 */
int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
{
    int len;

    if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
        goto end_int_array;

    if (len > 1 && buf[*offset] == 0x00)    /* ignore the negative byte */
    {
        len--;
        (*offset)++;
    }

    *object = (uint8_t *)malloc(len);
    memcpy(*object, &buf[*offset], len);
    *offset += len;

end_int_array:
    return len;
}
示例#13
0
/**
 * Get the components of a distinguished name 
 */
static int ICACHE_FLASH_ATTR asn1_get_oid_x520(const uint8_t *buf, int *offset)
{
    int dn_type = 0;
    int len;

    if ((len = asn1_next_obj(buf, offset, ASN1_OID)) < 0)
        goto end_oid;

    /* expect a sequence of 2.5.4.[x] where x is a one of distinguished name 
       components we are interested in. */
    if (len == 3 && buf[(*offset)++] == 0x55 && buf[(*offset)++] == 0x04)
        dn_type = buf[(*offset)++];
    else
    {
        *offset += len;     /* skip over it */
    }

end_oid:
    return dn_type;
}
示例#14
0
/**
 * Get the subject name (or the issuer) of a certificate.
 */
int asn1_name(const uint8_t *cert, int *offset, char *dn[])
{
    int ret = X509_NOT_OK;
    int dn_type = 0;
    char *name = NULL;
    char* name_prefix = NULL; /* GBG */
    
    if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
        goto end_name;

    while (asn1_next_obj(cert, offset, ASN1_SET) >= 0)
    {
        int i, found = 0;

        if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0) {  /* GBG */
            goto end_name;
        }
        /* get the oid */
        {
            int len = asn1_next_obj(cert, offset, ASN1_OID);
            int oid_offset = *offset;
            
            if (len < 0) goto end_name;
            if (len == 3 && cert[oid_offset] == 0x55 && cert[oid_offset+1] == 0x04) {
                dn_type = cert[oid_offset+2];
            } else {
                /* convert the OID to a string */
                name_prefix = asn1_oid_to_string(cert+oid_offset, len);
                if (name_prefix == NULL) goto end_name;
            }
            *offset += len;
        }
        if (asn1_get_printable_str(cert, offset, &name) < 0) {
            free(name);
            if (name_prefix) free(name_prefix);
            goto end_name;
        }
        /* add the prefix if there is one */
        if (name_prefix) {
            int name_prefix_len = (int)strlen(name_prefix);
            int name_len        = (int)strlen(name);
            char* compound = malloc(name_prefix_len+name_len+2);
            memcpy(compound, name_prefix, name_prefix_len);
            compound[name_prefix_len] = '=';
            memcpy(compound+name_prefix_len+1, name, name_len+1);
            free(name);
            free(name_prefix);
            name = compound;
            name_prefix = NULL;
        }

        /* find the distinguished named type */
        for (i = 0; i < X509_NUM_DN_TYPES; i++)
        {
            if (dn_type == g_dn_types[i])
            {
                if (dn[i] == NULL)
                {
                    dn[i] = name;
                    found = 1;
                    break;
                }
            }
        }

        if (found == 0) /* not found so get rid of it */
        {
            free(name);
        }
    }

    ret = X509_OK;
end_name:
    return ret;
}
示例#15
0
/**
 * Retrieve the notbefore and notafter certificate times.
 */
int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
{
    return (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0 ||
              asn1_get_utc_time(cert, offset, &x509_ctx->not_before) ||
              asn1_get_utc_time(cert, offset, &x509_ctx->not_after));
}
示例#16
0
文件: x509.c 项目: slaff/axtls-8266
/**
 * 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, begin_spki, end_spki;
    int ret = X509_NOT_OK, offset = 0, cert_size = 0;
    int version = 0;
    X509_CTX *x509_ctx;
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
    BI_CTX *bi_ctx;
#endif

    *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;

    /* optional version */
    if (cert[offset] == ASN1_EXPLICIT_TAG && 
            asn1_version(cert, &offset, &version) == X509_NOT_OK)
        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))
    {
        goto end_cert;
    }
    begin_spki = offset;
    if (asn1_public_key(cert, &offset, x509_ctx))
        goto end_cert;
    end_spki = offset;

    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);

    x509_ctx->spki_sha256 = malloc(SHA256_SIZE);
    SHA256_CTX spki_hash_ctx;
    SHA256_Init(&spki_hash_ctx);
    SHA256_Update(&spki_hash_ctx, &cert[begin_spki], end_spki-begin_spki);
    SHA256_Final(x509_ctx->spki_sha256, &spki_hash_ctx);

#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
    bi_ctx = x509_ctx->rsa_ctx->bi_ctx;

    /* use the appropriate signature algorithm */
    switch (x509_ctx->sig_type)
    {
        case 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);
        }
            break;

        case 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);
        }
            break;

        case SIG_TYPE_SHA256:
        {
            SHA256_CTX sha256_ctx;
            uint8_t sha256_dgst[SHA256_SIZE];
            SHA256_Init(&sha256_ctx);
            SHA256_Update(&sha256_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA256_Final(sha256_dgst, &sha256_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha256_dgst, SHA256_SIZE);
        }
            break;

        case SIG_TYPE_SHA384:
        {
            SHA384_CTX sha384_ctx;
            uint8_t sha384_dgst[SHA384_SIZE];
            SHA384_Init(&sha384_ctx);
            SHA384_Update(&sha384_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA384_Final(sha384_dgst, &sha384_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha384_dgst, SHA384_SIZE);
        }
            break;

        case SIG_TYPE_SHA512:
        {
            SHA512_CTX sha512_ctx;
            uint8_t sha512_dgst[SHA512_SIZE];
            SHA512_Init(&sha512_ctx);
            SHA512_Update(&sha512_ctx, &cert[begin_tbs], end_tbs-begin_tbs);
            SHA512_Final(sha512_dgst, &sha512_ctx);
            x509_ctx->digest = bi_import(bi_ctx, sha512_dgst, SHA512_SIZE);
        }
            break;
    }

    if (version == 2 && asn1_next_obj(cert, &offset, ASN1_V3_DATA) > 0)
    {
        x509_v3_subject_alt_name(cert, offset, x509_ctx);
        x509_v3_basic_constraints(cert, offset, x509_ctx);
        x509_v3_key_usage(cert, offset, x509_ctx);
    }

    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;

    /* 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;
}
示例#17
0
文件: x509.c 项目: cottsak/axtls-8266
/**
 * 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;
}
示例#18
0
文件: p12.c 项目: Lembed/uTLS
/*
 * Take a raw pkcs12 block and the decrypt it and turn it into a certificate(s)
 * and keys.
 */
int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
{
    uint8_t *buf = ssl_obj->buf;
    int len, iterations, auth_safes_start,
        auth_safes_end, auth_safes_len, key_offset, offset = 0;
    int all_certs = 0;
    uint8_t *version = NULL, *auth_safes = NULL, *cert, *orig_mac;
    uint8_t key[SHA1_SIZE];
    uint8_t mac[SHA1_SIZE];
    const uint8_t *salt;
    int uni_pass_len, ret = SSL_OK;
    char *uni_pass = make_uni_pass(password, &uni_pass_len);
    static const uint8_t pkcs_data[] = /* pkc7 data */
    { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 };
    static const uint8_t pkcs_encrypted[] = /* pkc7 encrypted */
    { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06 };
    static const uint8_t pkcs8_key_bag[] = /* 1.2.840.113549.1.12.10.1.2 */
    { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02 };

    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0) {
#ifdef CONFIG_SSL_FULL_MODE
        printf("Error: Invalid p12 ASN.1 file\n");
#endif
        goto error;
    }

    if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3) {
        ret = SSL_ERROR_INVALID_VERSION;
        goto error;
    }

    /* remove all the boring pcks7 bits */
    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
        len != sizeof(pkcs_data) ||
        memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
        goto error;

    offset += len;

    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0)
        goto error;

    /* work out the MAC start/end points (done on AuthSafes) */
    auth_safes_start = offset;
    auth_safes_end = offset;
    if (asn1_skip_obj(buf, &auth_safes_end, ASN1_SEQUENCE) < 0)
        goto error;

    auth_safes_len = auth_safes_end - auth_safes_start;
    auth_safes = malloc(auth_safes_len);

    memcpy(auth_safes, &buf[auth_safes_start], auth_safes_len);

    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
        (len != sizeof(pkcs_encrypted) ||
         memcmp(&buf[offset], pkcs_encrypted, sizeof(pkcs_encrypted))))
        goto error;

    offset += len;

    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        asn1_skip_obj(buf, &offset, ASN1_INTEGER) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
        len != sizeof(pkcs_data) ||
        memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
        goto error;

    offset += len;

    /* work out the salt for the certificate */
    if (get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_IMPLICIT_TAG)) < 0)
        goto error;

    /* decrypt the certificate */
    cert = &buf[offset];
    if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
                          len, PKCS12_KEY_ID)) < 0)
        goto error;

    offset += len;

    /* load the certificate */
    key_offset = 0;
    all_certs = asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE);

    /* keep going until all certs are loaded */
    while (key_offset < all_certs) {
        int cert_offset = key_offset;

        if (asn1_skip_obj(cert, &cert_offset, ASN1_SEQUENCE) < 0 ||
            asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
            asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
            asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
            asn1_next_obj(cert, &key_offset, ASN1_SEQUENCE) < 0 ||
            asn1_skip_obj(cert, &key_offset, ASN1_OID) < 0 ||
            asn1_next_obj(cert, &key_offset, ASN1_EXPLICIT_TAG) < 0 ||
            (len = asn1_next_obj(cert, &key_offset, ASN1_OCTET_STRING)) < 0)
            goto error;

        if ((ret = add_cert(ssl_ctx, &cert[key_offset], len)) < 0)
            goto error;

        key_offset = cert_offset;
    }

    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
        len != sizeof(pkcs_data) ||
        memcmp(&buf[offset], pkcs_data, sizeof(pkcs_data)))
        goto error;

    offset += len;

    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_OCTET_STRING) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OID)) < 0 ||
        (len != sizeof(pkcs8_key_bag)) ||
        memcmp(&buf[offset], pkcs8_key_bag, sizeof(pkcs8_key_bag)))
        goto error;

    offset += len;

    /* work out the salt for the private key */
    if (asn1_next_obj(buf, &offset, ASN1_EXPLICIT_TAG) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        get_pbe_params(buf, &offset, &salt, &iterations) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0)
        goto error;

    /* decrypt the private key */
    cert = &buf[offset];
    if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations, cert,
                          len, PKCS12_KEY_ID)) < 0)
        goto error;

    offset += len;

    /* load the private key */
    if ((ret = p8_add_key(ssl_ctx, cert)) < 0)
        goto error;

    /* miss out on friendly name, local key id etc */
    if (asn1_skip_obj(buf, &offset, ASN1_SET) < 0)
        goto error;

    /* work out the MAC */
    if (asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        asn1_next_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        asn1_skip_obj(buf, &offset, ASN1_SEQUENCE) < 0 ||
        (len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 ||
        len != SHA1_SIZE)
        goto error;

    orig_mac = &buf[offset];
    offset += len;

    /* get the salt */
    if ((len = asn1_next_obj(buf, &offset, ASN1_OCTET_STRING)) < 0 || len != 8)
        goto error;

    salt = &buf[offset];

    /* work out what the mac should be */
    if ((ret = p8_decrypt(uni_pass, uni_pass_len, salt, iterations,
                          key, SHA1_SIZE, PKCS12_MAC_ID)) < 0)
        goto error;

    hmac_sha1(auth_safes, auth_safes_len, key, SHA1_SIZE, mac);

    if (memcmp(mac, orig_mac, SHA1_SIZE)) {
        ret = SSL_ERROR_INVALID_HMAC;
        goto error;
    }

error:
    free(version);
    free(uni_pass);
    free(auth_safes);
    return ret;
}