diff --git a/src/crypto/axtls/aes.c b/src/crypto/axtls/aes.c index 298e4193..9154a515 100644 --- a/src/crypto/axtls/aes.c +++ b/src/crypto/axtls/aes.c @@ -238,9 +238,6 @@ void AES_set_key(AES_CTX *ctx, const uint8_t *key, memcpy(ctx->iv, iv, 16); } -#if 0 -/** currently unused function **/ - /** * Change a key for decryption. */ @@ -259,7 +256,6 @@ void AES_convert_key(AES_CTX *ctx) *k++ =w; } } -#endif /** * Encrypt a byte sequence (with a block size 16) using the AES cipher. diff --git a/src/crypto/axtls/axtls_asn1.c b/src/crypto/axtls/axtls_asn1.c new file mode 100644 index 00000000..74411c70 --- /dev/null +++ b/src/crypto/axtls/axtls_asn1.c @@ -0,0 +1,867 @@ +/* + * Copyright(C) 2006 Cameron Rich + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file asn1.c + * + * Some primitive asn methods for extraction rsa modulus information. It also + * is used for retrieving information from X.509 certificates. + */ + +#include +#include +#include +#include +#include "crypto.h" + +#define SIG_OID_PREFIX_SIZE 8 + +#define SIG_TYPE_MD2 0x02 +#define SIG_TYPE_MD5 0x04 +#define SIG_TYPE_SHA1 0x05 + +/* Must be an RSA algorithm with either SHA1 or MD5 for verifying to work */ +static const uint8_t sig_oid_prefix[SIG_OID_PREFIX_SIZE] = +{ + 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01 +}; + +/* CN, O, OU */ +static const uint8_t g_dn_types[] = { 3, 10, 11 }; + +static int get_asn1_length(const uint8_t *buf, int *offset) +{ + int len, i; + + if (!(buf[*offset] & 0x80)) /* short form */ + { + len = buf[(*offset)++]; + } + else /* long form */ + { + int length_bytes = buf[(*offset)++]&0x7f; + len = 0; + for (i = 0; i < length_bytes; i++) + { + len <<= 8; + len += buf[(*offset)++]; + } + } + + return len; +} + +/** + * 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); +} + +/** + * 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; +} + +/** + * 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; + + *object = (uint8_t *)malloc(len); + memcpy(*object, &buf[*offset], len); + *offset += len; + +end_int_array: + return len; +} + +#if 0 + +/** + * Get all the RSA private key specifics from an ASN.1 encoded file + */ +int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx) +{ + int offset = 7; + uint8_t *modulus, *priv_exp, *pub_exp; + int mod_len, priv_len, pub_len; +#ifdef CONFIG_BIGINT_CRT + uint8_t *p, *q, *dP, *dQ, *qInv; + int p_len, q_len, dP_len, dQ_len, qInv_len; +#endif + + /* not in der format */ + if (buf[0] != ASN1_SEQUENCE) /* basic sanity check */ + { +#ifdef CONFIG_SSL_FULL_MODE + printf("Error: This is not a valid ASN.1 file\n"); +#endif + return X509_INVALID_PRIV_KEY; + } + + /* initialise the RNG */ + RNG_initialize(buf, len); + + mod_len = asn1_get_int(buf, &offset, &modulus); + pub_len = asn1_get_int(buf, &offset, &pub_exp); + priv_len = asn1_get_int(buf, &offset, &priv_exp); + + if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0) + return X509_INVALID_PRIV_KEY; + +#ifdef CONFIG_BIGINT_CRT + p_len = asn1_get_int(buf, &offset, &p); + q_len = asn1_get_int(buf, &offset, &q); + dP_len = asn1_get_int(buf, &offset, &dP); + dQ_len = asn1_get_int(buf, &offset, &dQ); + qInv_len = asn1_get_int(buf, &offset, &qInv); + + if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0) + return X509_INVALID_PRIV_KEY; + + RSA_priv_key_new(rsa_ctx, + modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len, + p, p_len, q, p_len, dP, dP_len, dQ, dQ_len, qInv, qInv_len); + + free(p); + free(q); + free(dP); + free(dQ); + free(qInv); +#else + RSA_priv_key_new(rsa_ctx, + modulus, mod_len, pub_exp, pub_len, priv_exp, priv_len); +#endif + + free(modulus); + free(priv_exp); + free(pub_exp); + return X509_OK; +} + +/** + * 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; +} + +/** + * Get the version type of a certificate (which we don't actually care about) + */ +static int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx) +{ + int ret = X509_NOT_OK; + + (*offset) += 2; /* get past explicit tag */ + if (asn1_skip_obj(cert, offset, ASN1_INTEGER)) + goto end_version; + + ret = X509_OK; +end_version: + return ret; +} + +/** + * Retrieve the notbefore and notafter certificate times. + */ +static 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)); +} + +/** + * 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)++] == 0x04) + dn_type = buf[(*offset)++]; + else + { + *offset += len; /* skip over it */ + } + +end_oid: + return dn_type; +} + +/** + * 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; + + /* some certs have this awful crud in them for some reason */ + if (buf[*offset] != ASN1_PRINTABLE_STR && + buf[*offset] != ASN1_TELETEX_STR && buf[*offset] != ASN1_IA5_STR) + goto end_pnt_str; + + (*offset)++; + len = get_asn1_length(buf, offset); + *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; +} + +/** + * Get the subject name (or the issuer) of a certificate. + */ +static int asn1_name(const uint8_t *cert, int *offset, char *dn[]) +{ + int ret = X509_NOT_OK; + int dn_type; + char *tmp = NULL; + + 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; + + 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; +} + +/** + * Read the modulus and public exponent of a certificate. + */ +static 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, *pub_exp; + + 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)++; + + 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; +} + +#ifdef CONFIG_SSL_CERT_VERIFICATION +/** + * Read the signature of the certificate. + */ +static 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); + 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; +} + +/* + * Compare 2 distinguished name components for equality + * @return 0 if a match + */ +static int asn1_compare_dn_comp(const char *dn1, const char *dn2) +{ + int ret = 1; + + if ((dn1 && dn2 == NULL) || (dn1 == NULL && dn2)) goto err_no_match; + + ret = (dn1 && dn2) ? strcmp(dn1, dn2) : 0; + +err_no_match: + return ret; +} + +/** + * Clean up all of the CA certificates. + */ +void remove_ca_certs(CA_CERT_CTX *ca_cert_ctx) +{ + int i = 0; + + while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) + { + x509_free(ca_cert_ctx->cert[i]); + ca_cert_ctx->cert[i++] = NULL; + } + + free(ca_cert_ctx); +} + +/* + * Compare 2 distinguished names for equality + * @return 0 if a match + */ +static int asn1_compare_dn(char * const dn1[], char * const dn2[]) +{ + int i; + + for (i = 0; i < X509_NUM_DN_TYPES; i++) + { + if (asn1_compare_dn_comp(dn1[i], dn2[i])) + { + return 1; + } + } + + return 0; /* all good */ +} + +/** + * Retrieve the signature from a certificate. + */ +const uint8_t *x509_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; +} + +#endif + +/** + * Read the signature type of the certificate. We only support RSA-MD5 and + * RSA-SHA1 signature types. + */ +static 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 (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; + if (asn1_skip_obj(cert, offset, ASN1_NULL)) + goto end_check_sig; + ret = X509_OK; + +end_check_sig: + return ret; +} + +/** + * 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; + +#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ + /* use the appropriate signature algorithm (either SHA1 or MD5) */ + if (x509_ctx->sig_type == SIG_TYPE_MD5) + { + MD5_CTX md5_ctx; + uint8_t md5_dgst[MD5_SIZE]; + MD5Init(&md5_ctx); + MD5Update(&md5_ctx, &cert[begin_tbs], end_tbs-begin_tbs); + MD5Final(&md5_ctx, md5_dgst); + 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]; + SHA1Init(&sha_ctx); + SHA1Update(&sha_ctx, &cert[begin_tbs], end_tbs-begin_tbs); + SHA1Final(&sha_ctx, sha_dgst); + x509_ctx->digest = bi_import(bi_ctx, sha_dgst, SHA1_SIZE); + } + + offset = end_tbs; /* skip the v3 data */ + if (asn1_skip_obj(cert, &offset, ASN1_SEQUENCE) || + asn1_signature(cert, &offset, x509_ctx)) + goto end_cert; +#endif + + if (len) + { + *len = cert_size; + } + + ret = X509_OK; +end_cert: + +#ifdef CONFIG_SSL_FULL_MODE + if (ret) + { + printf("Error: Invalid X509 ASN.1 file\n"); + } +#endif + + return ret; +} + +/** + * Free an X.509 object's resources. + */ +void x509_free(X509_CTX *x509_ctx) +{ + X509_CTX *next; + int i; + + if (x509_ctx == NULL) /* if already null, then don't bother */ + return; + + for (i = 0; i < X509_NUM_DN_TYPES; i++) + { + free(x509_ctx->ca_cert_dn[i]); + free(x509_ctx->cert_dn[i]); + } + + free(x509_ctx->signature); + +#ifdef CONFIG_SSL_CERT_VERIFICATION + if (x509_ctx->digest) + { + bi_free(x509_ctx->rsa_ctx->bi_ctx, x509_ctx->digest); + } +#endif + + RSA_free(x509_ctx->rsa_ctx); + + next = x509_ctx->next; + free(x509_ctx); + x509_free(next); /* clear the chain */ +} + +#ifdef CONFIG_SSL_CERT_VERIFICATION +/** + * Do some basic checks on the certificate chain. + * + * Certificate verification consists of a number of checks: + * - A root certificate exists in the certificate store. + * - The date of the certificate is after the start date. + * - The date of the certificate is before the finish date. + * - The certificate chain is valid. + * - That the certificate(s) are not self-signed. + * - The signature of the certificate is valid. + */ +int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) +{ + int ret = X509_OK, i = 0; + bigint *cert_sig; + X509_CTX *next_cert = NULL; + BI_CTX *ctx; + bigint *mod, *expn; + struct timeval tv; + int match_ca_cert = 0; + + if (cert == NULL || ca_cert_ctx == NULL) + { + ret = X509_VFY_ERROR_NO_TRUSTED_CERT; + goto end_verify; + } + + /* last cert in the chain - look for a trusted cert */ + if (cert->next == NULL) + { + while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) + { + if (asn1_compare_dn(cert->ca_cert_dn, + ca_cert_ctx->cert[i]->cert_dn) == 0) + { + match_ca_cert = 1; + break; + } + + i++; + } + + if (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i]) + { + next_cert = ca_cert_ctx->cert[i]; + } + else /* trusted cert not found */ + { + ret = X509_VFY_ERROR_NO_TRUSTED_CERT; + goto end_verify; + } + } + else + { + next_cert = cert->next; + } + + 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; + } + + /* check the chain integrity */ + if (asn1_compare_dn(cert->ca_cert_dn, next_cert->cert_dn)) + { + ret = X509_VFY_ERROR_INVALID_CHAIN; + goto end_verify; + } + + /* check for self-signing */ + if (!match_ca_cert && asn1_compare_dn(cert->ca_cert_dn, cert->cert_dn) == 0) + { + ret = X509_VFY_ERROR_SELF_SIGNED; + goto end_verify; + } + + /* check the signature */ + ctx = cert->rsa_ctx->bi_ctx; + mod = next_cert->rsa_ctx->m; + expn = next_cert->rsa_ctx->e; + cert_sig = RSA_sign_verify(ctx, cert->signature, cert->sig_len, + bi_clone(ctx, mod), bi_clone(ctx, expn)); + + if (cert_sig) + { + ret = cert->digest ? /* check the signature */ + bi_compare(cert_sig, cert->digest) : + X509_VFY_ERROR_UNSUPPORTED_DIGEST; + bi_free(ctx, cert_sig); + + if (ret) + goto end_verify; + } + else + { + ret = X509_VFY_ERROR_BAD_SIGNATURE; + goto end_verify; + } + + /* go down the certificate chain using recursion. */ + if (ret == 0 && cert->next) + { + ret = x509_verify(ca_cert_ctx, next_cert); + } + +end_verify: + return ret; +} +#endif + +#if defined (CONFIG_SSL_FULL_MODE) +/** + * Used for diagnostics. + */ +void x509_print(CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) +{ + if (cert == NULL) + return; + + printf("---------------- CERT DEBUG ----------------\n"); + printf("* CA Cert Distinguished Name\n"); + if (cert->ca_cert_dn[X509_COMMON_NAME]) + { + printf("Common Name (CN):\t%s\n", cert->ca_cert_dn[X509_COMMON_NAME]); + } + + if (cert->ca_cert_dn[X509_ORGANIZATION]) + { + printf("Organization (O):\t%s\n", cert->ca_cert_dn[X509_ORGANIZATION]); + } + + if (cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]) + { + printf("Organizational Unit (OU): %s\n", + cert->ca_cert_dn[X509_ORGANIZATIONAL_TYPE]); + } + + printf("* Cert Distinguished Name\n"); + if (cert->cert_dn[X509_COMMON_NAME]) + { + printf("Common Name (CN):\t%s\n", cert->cert_dn[X509_COMMON_NAME]); + } + + if (cert->cert_dn[X509_ORGANIZATION]) + { + printf("Organization (O):\t%s\n", cert->cert_dn[X509_ORGANIZATION]); + } + + if (cert->cert_dn[X509_ORGANIZATIONAL_TYPE]) + { + printf("Organizational Unit (OU): %s\n", + cert->cert_dn[X509_ORGANIZATIONAL_TYPE]); + } + + printf("Not Before:\t\t%s", ctime(&cert->not_before)); + printf("Not After:\t\t%s", ctime(&cert->not_after)); + printf("RSA bitsize:\t\t%d\n", cert->rsa_ctx->num_octets*8); + printf("Sig Type:\t\t"); + switch (cert->sig_type) + { + case SIG_TYPE_MD5: + printf("MD5\n"); + break; + case SIG_TYPE_SHA1: + printf("SHA1\n"); + break; + case SIG_TYPE_MD2: + printf("MD2\n"); + break; + default: + printf("Unrecognized: %d\n", cert->sig_type); + break; + } + + printf("Verify:\t\t\t"); + + if (ca_cert_ctx) + { + x509_display_error(x509_verify(ca_cert_ctx, cert)); + } + + printf("\n"); +#if 0 + print_blob("Signature", cert->signature, cert->sig_len); + bi_print("Modulus", cert->rsa_ctx->m); + bi_print("Pub Exp", cert->rsa_ctx->e); +#endif + + if (ca_cert_ctx) + { + x509_print(ca_cert_ctx, cert->next); + } +} + +void x509_display_error(int error) +{ + switch (error) + { + case X509_NOT_OK: + printf("X509 not ok"); + break; + + case X509_VFY_ERROR_NO_TRUSTED_CERT: + printf("No trusted cert is available"); + break; + + case X509_VFY_ERROR_BAD_SIGNATURE: + printf("Bad signature"); + break; + + case X509_VFY_ERROR_NOT_YET_VALID: + printf("Cert is not yet valid"); + break; + + case X509_VFY_ERROR_EXPIRED: + printf("Cert has expired"); + break; + + case X509_VFY_ERROR_SELF_SIGNED: + printf("Cert is self-signed"); + break; + + case X509_VFY_ERROR_INVALID_CHAIN: + printf("Chain is invalid (check order of certs)"); + break; + + case X509_VFY_ERROR_UNSUPPORTED_DIGEST: + printf("Unsupported digest"); + break; + + case X509_INVALID_PRIV_KEY: + printf("Invalid private key"); + break; + } +} +#endif /* CONFIG_SSL_FULL_MODE */ + +#endif diff --git a/src/crypto/axtls/bigint.c b/src/crypto/axtls/bigint.c index 253707e7..2551f593 100644 --- a/src/crypto/axtls/bigint.c +++ b/src/crypto/axtls/bigint.c @@ -77,23 +77,14 @@ static void check(const bigint *bi); */ BI_CTX *bi_initialize(void) { + /* calloc() sets everything to zero */ BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX)); - - ctx->active_list = NULL; - ctx->active_count = 0; - ctx->free_list = NULL; - ctx->free_count = 0; - ctx->mod_offset = 0; -#ifdef CONFIG_BIGINT_MONTGOMERY - ctx->use_classical = 0; -#endif - + /* the radix */ ctx->bi_radix = alloc(ctx, 2); ctx->bi_radix->comps[0] = 0; ctx->bi_radix->comps[1] = 1; bi_permanent(ctx->bi_radix); - return ctx; } @@ -285,7 +276,7 @@ bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib) * @param bia [in] A bigint. * @param bib [in] Another bigint. * @param is_negative [out] If defined, indicates that the result was negative. - * is_negative may be NULL. + * is_negative may be null. * @return The result of the subtraction. The result is always positive. */ bigint *bi_subtract(BI_CTX *ctx, @@ -482,7 +473,7 @@ bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod) /* * Perform an integer divide on a bigint. */ -static bigint *bi_int_divide(__unused BI_CTX *ctx, bigint *biR, comp denom) +static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom) { int i = biR->size - 1; long_comp r = 0; @@ -781,7 +772,9 @@ void bi_free_mod(BI_CTX *ctx, int mod_offset) */ static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib) { - int i, j, i_plus_j, n = bia->size, t = bib->size; + int i, j, i_plus_j; + int n = bia->size; + int t = bib->size; bigint *biR = alloc(ctx, n + t); comp *sr = biR->comps; comp *sa = bia->comps; @@ -1059,7 +1052,7 @@ static bigint *alloc(BI_CTX *ctx, int size) #ifdef CONFIG_SSL_FULL_MODE printf("alloc: refs was not 0\n"); #endif - abort(); + abort(); /* create a stack trace from a core dump */ } more_comps(biR, size); @@ -1220,7 +1213,7 @@ static bigint *comp_mod(bigint *bi, int mod) /* * Barrett reduction has no need for some parts of the product, so ignore bits * of the multiply. This routine gives Barrett its big performance - * improvements over classical/Montgomery reduction methods. + * improvements over Classical/Montgomery reduction methods. */ static bigint *partial_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, int inner_partial, int outer_partial) @@ -1293,10 +1286,10 @@ static bigint *partial_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, } /** - * @brief Perform a single barrett reduction. + * @brief Perform a single Barrett reduction. * @param ctx [in] The bigint session context. * @param bi [in] A bigint. - * @return The result of the barrett reduction. + * @return The result of the Barrett reduction. */ bigint *bi_barrett(BI_CTX *ctx, bigint *bi) { @@ -1308,7 +1301,7 @@ bigint *bi_barrett(BI_CTX *ctx, bigint *bi) check(bi); check(bim); - /* use classical method instead - Barrett cannot help here */ + /* use Classical method instead - Barrett cannot help here */ if (bi->size > k*2) { return bi_mod(ctx, bi); @@ -1397,9 +1390,7 @@ bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) #ifdef CONFIG_BIGINT_SLIDING_WINDOW for (j = i; j > 32; j /= 5) /* work out an optimum size */ - { window_size++; - } /* work out the slide constants */ precompute_slide_window(ctx, window_size, bi); @@ -1420,15 +1411,11 @@ bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp) int part_exp = 0; if (l < 0) /* LSB of exponent will always be 1 */ - { l = 0; - } else { while (exp_bit_is_one(biexp, l) == 0) - { l++; /* go back up */ - } } /* build up the section of the exponent */ diff --git a/src/crypto/axtls/bigint.h b/src/crypto/axtls/bigint.h index e233d798..5a13c5ae 100644 --- a/src/crypto/axtls/bigint.h +++ b/src/crypto/axtls/bigint.h @@ -74,14 +74,14 @@ bigint *bi_str_import(BI_CTX *ctx, const char *data); * appropriate reduction technique (which is bi_mod() when doing classical * reduction). */ -#if defined(CONFIG_BIGINT_CLASSICAL) -#define bi_residue(A, B) bi_mod(A, B) +#if defined(CONFIG_BIGINT_MONTGOMERY) +#define bi_residue(A, B) bi_mont(A, B) +bigint *bi_mont(BI_CTX *ctx, bigint *bixy); #elif defined(CONFIG_BIGINT_BARRETT) #define bi_residue(A, B) bi_barrett(A, B) bigint *bi_barrett(BI_CTX *ctx, bigint *bi); -#else /* CONFIG_BIGINT_MONTGOMERY */ -#define bi_residue(A, B) bi_mont(A, B) -bigint *bi_mont(BI_CTX *ctx, bigint *bixy); +#else /* if defined(CONFIG_BIGINT_CLASSICAL) */ +#define bi_residue(A, B) bi_mod(A, B) #endif #ifdef CONFIG_BIGINT_SQUARE diff --git a/src/crypto/axtls/crypto.h b/src/crypto/axtls/crypto.h index 855282fa..de1dbeb4 100644 --- a/src/crypto/axtls/crypto.h +++ b/src/crypto/axtls/crypto.h @@ -54,9 +54,7 @@ void AES_set_key(AES_CTX *ctx, const uint8_t *key, void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length); void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length); -#if 0 /** currently unused function **/ void AES_convert_key(AES_CTX *ctx); -#endif /************************************************************************** * RC4 declarations @@ -126,7 +124,12 @@ void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, void RNG_initialize(const uint8_t *seed_buf, int size); void RNG_terminate(void); void get_random(int num_rand_bytes, uint8_t *rand_data); -void get_random_NZ(int num_rand_bytes, uint8_t *rand_data); +//void get_random_NZ(int num_rand_bytes, uint8_t *rand_data); + +#include +static inline void get_random_NZ(int num_rand_bytes, uint8_t *rand_data) { + memset ( rand_data, 0x01, num_rand_bytes ); +} /************************************************************************** * RSA declarations @@ -165,15 +168,15 @@ void RSA_pub_key_new(RSA_CTX **rsa_ctx, const uint8_t *modulus, int mod_len, const uint8_t *pub_exp, int pub_len); void RSA_free(RSA_CTX *ctx); -int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, +int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, int is_decryption); -bigint *RSA_private(RSA_CTX *c, bigint *bi_msg); +bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg); #ifdef CONFIG_SSL_CERT_VERIFICATION bigint *RSA_raw_sign_verify(RSA_CTX *c, bigint *bi_msg); bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, bigint *modulus, bigint *pub_exp); -bigint *RSA_public(RSA_CTX *c, bigint *bi_msg); -int RSA_encrypt(RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, +bigint *RSA_public(const RSA_CTX *c, bigint *bi_msg); +int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, uint8_t *out_data, int is_signing); void RSA_print(const RSA_CTX *ctx); #endif diff --git a/src/crypto/axtls/os_port.h b/src/crypto/axtls/os_port.h index 39e0fb54..babdbfad 100644 --- a/src/crypto/axtls/os_port.h +++ b/src/crypto/axtls/os_port.h @@ -27,9 +27,6 @@ static inline void close ( int fd __unused ) { } typedef void FILE; -#define SEEK_SET 0 -#define SEEK_CUR 0 -#define SEEK_END 0 static inline FILE * fopen ( const char *filename __unused, const char *mode __unused ) { diff --git a/src/crypto/axtls/rsa.c b/src/crypto/axtls/rsa.c index 69db9ae7..389eda57 100644 --- a/src/crypto/axtls/rsa.c +++ b/src/crypto/axtls/rsa.c @@ -28,7 +28,7 @@ #include "crypto.h" #ifdef CONFIG_BIGINT_CRT -static bigint *bi_crt(RSA_CTX *rsa, bigint *bi); +static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi); #endif void RSA_priv_key_new(RSA_CTX **ctx, @@ -72,7 +72,7 @@ void RSA_pub_key_new(RSA_CTX **ctx, { RSA_CTX *rsa_ctx; BI_CTX *bi_ctx = bi_initialize(); - *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX)); /* reset to all 0 */ + *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX)); rsa_ctx = *ctx; rsa_ctx->bi_ctx = bi_ctx; rsa_ctx->num_octets = (mod_len & 0xFFF0); @@ -126,8 +126,8 @@ void RSA_free(RSA_CTX *rsa_ctx) * @return The number of bytes that were originally encrypted. -1 on error. * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125 */ -int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, - int is_decryption) +int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, + uint8_t *out_data, int is_decryption) { int byte_size = ctx->num_octets; uint8_t *block; @@ -155,10 +155,9 @@ int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */ { while (block[i++] == 0xff && i < byte_size); + if (block[i-2] != 0xff) - { i = byte_size; /*ensure size is 0 */ - } } else /* PKCS1.5 encryption padding is random */ #endif @@ -169,9 +168,7 @@ int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, /* get only the bit we want */ if (size > 0) - { memcpy(out_data, &block[i], size); - } free(block); return size ? size : -1; @@ -180,7 +177,7 @@ int RSA_decrypt(RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data, /** * Performs m = c^d mod n */ -bigint *RSA_private(RSA_CTX *c, bigint *bi_msg) +bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg) { #ifdef CONFIG_BIGINT_CRT return bi_crt(c, bi_msg); @@ -197,7 +194,7 @@ bigint *RSA_private(RSA_CTX *c, bigint *bi_msg) * This should really be in bigint.c (and was at one stage), but needs * access to the RSA_CTX context... */ -static bigint *bi_crt(RSA_CTX *rsa, bigint *bi) +static bigint *bi_crt(const RSA_CTX *rsa, bigint *bi) { BI_CTX *ctx = rsa->bi_ctx; bigint *m1, *m2, *h; @@ -245,7 +242,7 @@ void RSA_print(const RSA_CTX *rsa_ctx) /** * Performs c = m^e mod n */ -bigint *RSA_public(RSA_CTX *c, bigint *bi_msg) +bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg) { c->bi_ctx->mod_offset = BIGINT_M_OFFSET; return bi_mod_power(c->bi_ctx, bi_msg, c->e); @@ -255,7 +252,7 @@ bigint *RSA_public(RSA_CTX *c, bigint *bi_msg) * Use PKCS1.5 for encryption/signing. * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125 */ -int RSA_encrypt(RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, +int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, uint8_t *out_data, int is_signing) { int byte_size = ctx->num_octets; @@ -273,10 +270,7 @@ int RSA_encrypt(RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, else /* randomize the encryption padding with non-zero bytes */ { out_data[1] = 2; - memset(&out_data[2], 0x01, num_pads_needed); -#if 0 get_random_NZ(num_pads_needed, &out_data[2]); -#endif } out_data[2+num_pads_needed] = 0; @@ -291,18 +285,19 @@ int RSA_encrypt(RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, } #if 0 - /** * Take a signature and decrypt it. */ bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, bigint *modulus, bigint *pub_exp) { - uint8_t *block = (uint8_t *)malloc(sig_len); + uint8_t *block; int i, size; bigint *decrypted_bi, *dat_bi; bigint *bir = NULL; + block = (uint8_t *)malloc(sig_len); + /* decrypt */ dat_bi = bi_import(ctx, sig, sig_len); ctx->mod_offset = BIGINT_M_OFFSET; @@ -332,7 +327,6 @@ bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len, free(block); return bir; } - #endif #endif /* CONFIG_SSL_CERT_VERIFICATION */