Explorar o código

Update axtls to version 2.14

mingodad %!s(int64=8) %!d(string=hai) anos
pai
achega
cf3b01bac8

+ 1 - 3
SquiLu-ext/sq_axtls.c

@@ -172,7 +172,7 @@ static SQRESULT sq_ssl_ctx_client_new(HSQUIRRELVM v){
     SQ_OPT_STRING(v, 3, session_id, NULL);
     SQ_OPT_STRING(v, 3, session_id, NULL);
     SQ_OPT_INTEGER(v, 4, size, -1);
     SQ_OPT_INTEGER(v, 4, size, -1);
 	SSL *ssl = ssl_client_new(self, client_fd, (const uint8_t *)session_id,
 	SSL *ssl = ssl_client_new(self, client_fd, (const uint8_t *)session_id,
-                           size >= 0 ? size : session_id_size);
+                           size >= 0 ? size : session_id_size, NULL);
     SQRESULT rc = ssl_constructor(v, ssl, 1);
     SQRESULT rc = ssl_constructor(v, ssl, 1);
     if(rc == SQ_ERROR && ssl){
     if(rc == SQ_ERROR && ssl){
         ssl_free(ssl);
         ssl_free(ssl);
@@ -361,8 +361,6 @@ static KeyIntType axtls_constants[] = {
     MK_CONST(SSL_ALERT_NO_RENEGOTIATION),
     MK_CONST(SSL_ALERT_NO_RENEGOTIATION),
     MK_CONST(SSL_AES128_SHA),
     MK_CONST(SSL_AES128_SHA),
     MK_CONST(SSL_AES256_SHA),
     MK_CONST(SSL_AES256_SHA),
-    MK_CONST(SSL_RC4_128_SHA),
-    MK_CONST(SSL_RC4_128_MD5),
     MK_CONST(SSL_BUILD_SKELETON_MODE),
     MK_CONST(SSL_BUILD_SKELETON_MODE),
     MK_CONST(SSL_BUILD_SERVER_ONLY),
     MK_CONST(SSL_BUILD_SERVER_ONLY),
     MK_CONST(SSL_BUILD_ENABLE_VERIFICATION),
     MK_CONST(SSL_BUILD_ENABLE_VERIFICATION),

+ 1 - 4
myaxtls/aes.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
+ * Copyright (c) 2007-2016, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  * 
  * 
@@ -38,8 +38,6 @@
 #include "os_port.h"
 #include "os_port.h"
 #include "crypto.h"
 #include "crypto.h"
 
 
-/* all commented out in skeleton mode */
-#ifndef CONFIG_SSL_SKELETON_MODE
 
 
 #define rot1(x) (((x) << 24) | ((x) >> 8))
 #define rot1(x) (((x) << 24) | ((x) >> 8))
 #define rot2(x) (((x) << 16) | ((x) >> 16))
 #define rot2(x) (((x) << 16) | ((x) >> 16))
@@ -454,4 +452,3 @@ static void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
     }
     }
 }
 }
 
 
-#endif

+ 148 - 27
myaxtls/asn1.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007-2015, Cameron Rich
+ * Copyright (c) 2007-2016, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  * 
  * 
@@ -80,8 +80,18 @@ static const uint8_t sig_subject_alt_name[] =
     0x55, 0x1d, 0x11
     0x55, 0x1d, 0x11
 };
 };
 
 
-/* CN, O, OU */
-static const uint8_t g_dn_types[] = { 3, 10, 11 };
+static const uint8_t sig_basic_constraints[] =
+{
+    0x55, 0x1d, 0x13
+};
+
+static const uint8_t sig_key_usage[] =
+{
+    0x55, 0x1d, 0x0f
+};
+
+/* CN, O, OU, L, C, ST */
+static const uint8_t g_dn_types[] = { 3, 10, 11, 7, 6, 8 };
 
 
 uint32_t get_asn1_length(const uint8_t *buf, int *offset)
 uint32_t get_asn1_length(const uint8_t *buf, int *offset)
 {
 {
@@ -141,12 +151,12 @@ int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type)
  * Read an integer value for ASN.1 data
  * Read an integer value for ASN.1 data
  * Note: This function allocates memory which must be freed by the user.
  * 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 asn1_get_big_int(const uint8_t *buf, int *offset, uint8_t **object)
 {
 {
     int len;
     int len;
 
 
     if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
     if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0)
-        goto end_int_array;
+        goto end_big_int;
 
 
     if (len > 1 && buf[*offset] == 0x00)    /* ignore the negative byte */
     if (len > 1 && buf[*offset] == 0x00)    /* ignore the negative byte */
     {
     {
@@ -158,10 +168,91 @@ int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object)
     memcpy(*object, &buf[*offset], len);
     memcpy(*object, &buf[*offset], len);
     *offset += len;
     *offset += len;
 
 
-end_int_array:
+end_big_int:
     return len;
     return len;
 }
 }
 
 
+/**
+ * Read an integer value for ASN.1 data
+ */
+int asn1_get_int(const uint8_t *buf, int *offset, int32_t *val)
+{
+    int res = X509_OK;
+    int len;
+    int i;
+
+    if ((len = asn1_next_obj(buf, offset, ASN1_INTEGER)) < 0 || 
+                len > sizeof(int32_t))
+    {
+        res = X509_NOT_OK;
+        goto end_int;
+    }
+
+    *val = 0;
+    for (i = 0; i < len; i++)
+    {
+        *val <<= 8;
+        *val |= buf[(*offset)++];
+    }
+
+end_int:
+    return res;
+}
+
+/**
+ * Read an boolean value for ASN.1 data
+ */
+int asn1_get_bool(const uint8_t *buf, int *offset, bool *val)
+{
+    int res = X509_OK;
+
+    if (asn1_next_obj(buf, offset, ASN1_BOOLEAN) != 1)
+    {
+        res = X509_NOT_OK;
+        goto end_bool;
+    }
+
+    /* DER demands that "If the encoding represents the boolean value TRUE,
+       its single contents octet shall have all eight bits set to one."
+       Thus only 0 and 255 are valid encoded values. */
+    *val = buf[(*offset)++] == 0xFF;
+
+end_bool:
+    return res;
+}
+
+/**
+ * Convert an ASN.1 bit string into a 32 bit integer. Used for key usage
+ */
+int asn1_get_bit_string_as_int(const uint8_t *buf, int *offset, uint32_t *val)
+{
+    int res = X509_OK;
+    int len, i;
+
+    if ((len = asn1_next_obj(buf, offset, ASN1_BIT_STRING)) < 0 || len > 5)
+    {
+        res = X509_NOT_OK;
+        goto end_bit_string_as_int;
+    }
+
+    /* number of bits left unused in the final byte of content */
+    (*offset)++;
+    len--;
+    *val = 0;
+
+    /* not sure why key usage doesn't used proper DER spec version */
+    for (i = len-1; i >= 0; --i)
+    {
+        *val <<= 8;
+        *val |= buf[(*offset) + i];
+    }
+
+    *offset += len;
+
+end_bit_string_as_int:
+    return res;
+}
+
 /**
 /**
  * Get all the RSA private key specifics from an ASN.1 encoded file 
  * Get all the RSA private key specifics from an ASN.1 encoded file 
  */
  */
@@ -187,19 +278,19 @@ int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx)
     /* Use the private key to mix up the RNG if possible. */
     /* Use the private key to mix up the RNG if possible. */
     RNG_custom_init(buf, len);
     RNG_custom_init(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);
+    mod_len = asn1_get_big_int(buf, &offset, &modulus);
+    pub_len = asn1_get_big_int(buf, &offset, &pub_exp);
+    priv_len = asn1_get_big_int(buf, &offset, &priv_exp);
 
 
     if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
     if (mod_len <= 0 || pub_len <= 0 || priv_len <= 0)
         return X509_INVALID_PRIV_KEY;
         return X509_INVALID_PRIV_KEY;
 
 
 #ifdef CONFIG_BIGINT_CRT
 #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);
+    p_len = asn1_get_big_int(buf, &offset, &p);
+    q_len = asn1_get_big_int(buf, &offset, &q);
+    dP_len = asn1_get_big_int(buf, &offset, &dP);
+    dQ_len = asn1_get_big_int(buf, &offset, &dQ);
+    qInv_len = asn1_get_big_int(buf, &offset, &qInv);
 
 
     if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
     if (p_len <= 0 || q_len <= 0 || dP_len <= 0 || dQ_len <= 0 || qInv_len <= 0)
         return X509_INVALID_PRIV_KEY;
         return X509_INVALID_PRIV_KEY;
@@ -243,13 +334,16 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
         memset(&tm, 0, sizeof(struct tm));
         memset(&tm, 0, sizeof(struct tm));
         tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
         tm.tm_year = (buf[t_offset] - '0')*10 + (buf[t_offset+1] - '0');
 
 
-        if (tm.tm_year <= 50)    /* 1951-2050 thing */
+        if (tm.tm_year < 50)    /* 1951-2050 thing */
         {
         {
             tm.tm_year += 100;
             tm.tm_year += 100;
         }
         }
 
 
         tm.tm_mon = (buf[t_offset+2] - '0')*10 + (buf[t_offset+3] - '0') - 1;
         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');
         tm.tm_mday = (buf[t_offset+4] - '0')*10 + (buf[t_offset+5] - '0');
+        tm.tm_hour = (buf[t_offset+6] - '0')*10 + (buf[t_offset+7] - '0');
+        tm.tm_min = (buf[t_offset+8] - '0')*10 + (buf[t_offset+9] - '0');
+        tm.tm_sec = (buf[t_offset+10] - '0')*10 + (buf[t_offset+11] - '0');
         *t = mktime(&tm);
         *t = mktime(&tm);
         *offset += len;
         *offset += len;
         ret = X509_OK;
         ret = X509_OK;
@@ -291,19 +385,13 @@ static int asn1_get_utc_time(const uint8_t *buf, int *offset, time_t *t)
 }
 }
 
 
 /**
 /**
- * Get the version type of a certificate (which we don't actually care about)
+ * Get the version type of a certificate
  */
  */
-int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
+int asn1_version(const uint8_t *cert, int *offset, int *val)
 {
 {
-    int ret = X509_NOT_OK;
 
 
     (*offset) += 2;        /* get past explicit tag */
     (*offset) += 2;        /* get past explicit tag */
-    if (asn1_skip_obj(cert, offset, ASN1_INTEGER))
-        goto end_version;
-
-    ret = X509_OK;
-end_version:
-    return ret;
+    return asn1_get_int(cert, offset, val);
 }
 }
 
 
 /**
 /**
@@ -453,8 +541,8 @@ int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx)
     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
     if (asn1_next_obj(cert, offset, ASN1_SEQUENCE) < 0)
         goto end_pub_key;
         goto end_pub_key;
 
 
-    mod_len = asn1_get_int(cert, offset, &modulus);
-    pub_len = asn1_get_int(cert, offset, &pub_exp);
+    mod_len = asn1_get_big_int(cert, offset, &modulus);
+    pub_len = asn1_get_big_int(cert, offset, &pub_exp);
 
 
     RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
     RSA_pub_key_new(&x509_ctx->rsa_ctx, modulus, mod_len, pub_exp, pub_len);
 
 
@@ -574,7 +662,7 @@ int asn1_find_oid(const uint8_t* cert, int* offset,
     return 0;
     return 0;
 }
 }
 
 
-int asn1_find_subjectaltname(const uint8_t* cert, int offset)
+int asn1_is_subject_alt_name(const uint8_t *cert, int offset)
 {
 {
     if (asn1_find_oid(cert, &offset, sig_subject_alt_name, 
     if (asn1_find_oid(cert, &offset, sig_subject_alt_name, 
                                 sizeof(sig_subject_alt_name)))
                                 sizeof(sig_subject_alt_name)))
@@ -585,6 +673,39 @@ int asn1_find_subjectaltname(const uint8_t* cert, int offset)
     return 0;
     return 0;
 }
 }
 
 
+int asn1_is_basic_constraints(const uint8_t *cert, int offset)
+{
+    if (asn1_find_oid(cert, &offset, sig_basic_constraints, 
+                                sizeof(sig_basic_constraints)))
+    {
+        return offset;
+    }
+
+    return 0;
+}
+
+int asn1_is_key_usage(const uint8_t *cert, int offset)
+{
+    if (asn1_find_oid(cert, &offset, sig_key_usage, 
+                                sizeof(sig_key_usage)))
+    {
+        return offset;
+    }
+
+    return 0;
+}
+
+bool asn1_is_critical_ext(const uint8_t *buf, int *offset)
+{
+    /* critical is optional */
+    bool res = false;
+
+    if (asn1_next_obj(buf, offset, ASN1_BOOLEAN) == 1)
+        res = buf[(*offset)++] == 0xFF;
+
+    return res;
+}
+
 #endif /* CONFIG_SSL_CERT_VERIFICATION */
 #endif /* CONFIG_SSL_CERT_VERIFICATION */
 
 
 /**
 /**

+ 1 - 0
myaxtls/axtls.cbp

@@ -114,6 +114,7 @@
 			<Add option="-DAXTLS_LIBRARY=1" />
 			<Add option="-DAXTLS_LIBRARY=1" />
 			<Add option="-DAS_STATIC_LIB=1" />
 			<Add option="-DAS_STATIC_LIB=1" />
 			<Add option="-DCONFIG_OPENSSL_COMPATIBLE=1" />
 			<Add option="-DCONFIG_OPENSSL_COMPATIBLE=1" />
+			<Add option="-DCONFIG_USE_DEV_URANDOM=1" />
 		</Compiler>
 		</Compiler>
 		<Linker>
 		<Linker>
 			<Add option="-s" />
 			<Add option="-s" />

+ 3 - 1
myaxtls/crypto.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007-2015, Cameron Rich
+ * Copyright (c) 2007-2016, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  * 
  * 
@@ -201,6 +201,8 @@ void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
         int key_len, uint8_t *digest);
         int key_len, uint8_t *digest);
 void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, 
 void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, 
         int key_len, uint8_t *digest);
         int key_len, uint8_t *digest);
+void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest);
 
 
 /**************************************************************************
 /**************************************************************************
  * RSA declarations 
  * RSA declarations 

+ 7 - 3
myaxtls/crypto_misc.c

@@ -124,8 +124,12 @@ EXP_FUNC void STDCALL RNG_initialize()
     /* start of with a stack to copy across */
     /* start of with a stack to copy across */
     int i;
     int i;
     memcpy(entropy_pool, &i, ENTROPY_POOL_SIZE);
     memcpy(entropy_pool, &i, ENTROPY_POOL_SIZE);
+#if defined(CONFIG_USE_DEV_URANDOM)
+    rand_r((unsigned int *)entropy_pool); 
+#else
     srand((unsigned int)&i); 
     srand((unsigned int)&i); 
 #endif
 #endif
+#endif
 }
 }
 
 
 /**
 /**
@@ -168,7 +172,7 @@ EXP_FUNC int STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
 #else   /* nothing else to use, so use a custom RNG */
 #else   /* nothing else to use, so use a custom RNG */
     /* The method we use when we've got nothing better. Use RC4, time 
     /* The method we use when we've got nothing better. Use RC4, time 
        and a couple of random seeds to generate a random sequence */
        and a couple of random seeds to generate a random sequence */
-    RC4_CTX rng_ctx;
+    AES_CTX rng_ctx;
     struct timeval tv;
     struct timeval tv;
     MD5_CTX rng_digest_ctx;
     MD5_CTX rng_digest_ctx;
     uint8_t digest[MD5_SIZE];
     uint8_t digest[MD5_SIZE];
@@ -187,10 +191,10 @@ EXP_FUNC int STDCALL get_random(int num_rand_bytes, uint8_t *rand_data)
     MD5_Final(digest, &rng_digest_ctx);
     MD5_Final(digest, &rng_digest_ctx);
 
 
     /* come up with the random sequence */
     /* come up with the random sequence */
-    RC4_setup(&rng_ctx, digest, MD5_SIZE); /* use as a key */
+    AES_set_key(&rng_ctx, digest, (const uint8_t *)ep, AES_MODE_128); /* use as a key */
     memcpy(rand_data, entropy_pool, num_rand_bytes < ENTROPY_POOL_SIZE ?
     memcpy(rand_data, entropy_pool, num_rand_bytes < ENTROPY_POOL_SIZE ?
 				num_rand_bytes : ENTROPY_POOL_SIZE);
 				num_rand_bytes : ENTROPY_POOL_SIZE);
-    RC4_crypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
+    AES_cbc_encrypt(&rng_ctx, rand_data, rand_data, num_rand_bytes);
 
 
     /* move things along */
     /* move things along */
     for (i = ENTROPY_POOL_SIZE-1; i >= MD5_SIZE ; i--)
     for (i = ENTROPY_POOL_SIZE-1; i >= MD5_SIZE ; i--)

+ 45 - 9
myaxtls/crypto_misc.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007-2015, Cameron Rich
+ * Copyright (c) 2007-2017, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -39,6 +39,7 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
+#include <stdbool.h>
 #include "crypto.h"
 #include "crypto.h"
 #include "bigint.h"
 #include "bigint.h"
 
 
@@ -56,14 +57,33 @@ extern "C" {
 #define X509_VFY_ERROR_UNSUPPORTED_DIGEST   -8
 #define X509_VFY_ERROR_UNSUPPORTED_DIGEST   -8
 #define X509_INVALID_PRIV_KEY               -9
 #define X509_INVALID_PRIV_KEY               -9
 #define X509_MAX_CERTS                      -10
 #define X509_MAX_CERTS                      -10
+#define X509_VFY_ERROR_BASIC_CONSTRAINT     -11
 
 
 /*
 /*
  * The Distinguished Name
  * The Distinguished Name
  */
  */
-#define X509_NUM_DN_TYPES                   3
+#define X509_NUM_DN_TYPES                   6
 #define X509_COMMON_NAME                    0
 #define X509_COMMON_NAME                    0
 #define X509_ORGANIZATION                   1
 #define X509_ORGANIZATION                   1
 #define X509_ORGANIZATIONAL_UNIT            2
 #define X509_ORGANIZATIONAL_UNIT            2
+#define X509_LOCATION                       3
+#define X509_COUNTRY                        4
+#define X509_STATE                          5
+
+/*
+ * Key Usage bits
+ */
+#define IS_SET_KEY_USAGE_FLAG(A, B)          (A->key_usage & B)
+
+#define KEY_USAGE_DIGITAL_SIGNATURE         0x0080
+#define KEY_USAGE_NON_REPUDIATION           0x0040
+#define KEY_USAGE_KEY_ENCIPHERMENT          0x0020
+#define KEY_USAGE_DATA_ENCIPHERMENT         0x0010
+#define KEY_USAGE_KEY_AGREEMENT             0x0008
+#define KEY_USAGE_KEY_CERT_SIGN             0x0004
+#define KEY_USAGE_CRL_SIGN                  0x0002
+#define KEY_USAGE_ENCIPHER_ONLY             0x0001
+#define KEY_USAGE_DECIPHER_ONLY             0x8000
 
 
 struct _x509_ctx
 struct _x509_ctx
 {
 {
@@ -73,10 +93,19 @@ struct _x509_ctx
     time_t not_before;
     time_t not_before;
     time_t not_after;
     time_t not_after;
     uint8_t *signature;
     uint8_t *signature;
-    uint16_t sig_len;
-    uint8_t sig_type;
     RSA_CTX *rsa_ctx;
     RSA_CTX *rsa_ctx;
     bigint *digest;
     bigint *digest;
+    uint16_t sig_len;
+    uint8_t sig_type;
+    bool basic_constraint_present;
+    bool basic_constraint_is_critical;
+    bool key_usage_present;
+    bool key_usage_is_critical;
+    bool subject_alt_name_present;
+    bool subject_alt_name_is_critical;
+    bool basic_constraint_cA;
+    int basic_constraint_pathLenConstraint;
+    uint32_t key_usage;
     struct _x509_ctx *next;
     struct _x509_ctx *next;
 };
 };
 
 
@@ -93,7 +122,8 @@ typedef struct
 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx);
 int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx);
 void x509_free(X509_CTX *x509_ctx);
 void x509_free(X509_CTX *x509_ctx);
 #ifdef CONFIG_SSL_CERT_VERIFICATION
 #ifdef CONFIG_SSL_CERT_VERIFICATION
-int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert);
+int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert, 
+        int *pathLenConstraint);
 #endif
 #endif
 #ifdef CONFIG_SSL_FULL_MODE
 #ifdef CONFIG_SSL_FULL_MODE
 void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx);
 void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx);
@@ -103,6 +133,7 @@ const char * x509_display_error(int error);
 /**************************************************************************
 /**************************************************************************
  * ASN1 declarations
  * ASN1 declarations
  **************************************************************************/
  **************************************************************************/
+#define ASN1_BOOLEAN            0x01
 #define ASN1_INTEGER            0x02
 #define ASN1_INTEGER            0x02
 #define ASN1_BIT_STRING         0x03
 #define ASN1_BIT_STRING         0x03
 #define ASN1_OCTET_STRING       0x04
 #define ASN1_OCTET_STRING       0x04
@@ -125,7 +156,6 @@ const char * x509_display_error(int error);
 #define ASN1_EXPLICIT_TAG       0xa0
 #define ASN1_EXPLICIT_TAG       0xa0
 #define ASN1_V3_DATA			0xa3
 #define ASN1_V3_DATA			0xa3
 
 
-#define SIG_TYPE_MD2            0x02
 #define SIG_TYPE_MD5            0x04
 #define SIG_TYPE_MD5            0x04
 #define SIG_TYPE_SHA1           0x05
 #define SIG_TYPE_SHA1           0x05
 #define SIG_TYPE_SHA256         0x0b
 #define SIG_TYPE_SHA256         0x0b
@@ -136,15 +166,21 @@ uint32_t get_asn1_length(const uint8_t *buf, int *offset);
 int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx);
 int asn1_get_private_key(const uint8_t *buf, int len, RSA_CTX **rsa_ctx);
 int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type);
 int asn1_next_obj(const uint8_t *buf, int *offset, int obj_type);
 int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type);
 int asn1_skip_obj(const uint8_t *buf, int *offset, int obj_type);
-int asn1_get_int(const uint8_t *buf, int *offset, uint8_t **object);
-int asn1_version(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
+int asn1_get_big_int(const uint8_t *buf, int *offset, uint8_t **object);
+int asn1_get_int(const uint8_t *buf, int *offset, int32_t *val);
+int asn1_get_bool(const uint8_t *buf, int *offset, bool *val);
+int asn1_get_bit_string_as_int(const uint8_t *buf, int *offset, uint32_t *val);
+int asn1_version(const uint8_t *cert, int *offset, int *val);
 int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
 int asn1_validity(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
 int asn1_name(const uint8_t *cert, int *offset, char *dn[]);
 int asn1_name(const uint8_t *cert, int *offset, char *dn[]);
 int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
 int asn1_public_key(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
 #ifdef CONFIG_SSL_CERT_VERIFICATION
 #ifdef CONFIG_SSL_CERT_VERIFICATION
 int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
 int asn1_signature(const uint8_t *cert, int *offset, X509_CTX *x509_ctx);
-int asn1_find_subjectaltname(const uint8_t* cert, int offset);
 int asn1_compare_dn(char * const dn1[], char * const dn2[]);
 int asn1_compare_dn(char * const dn1[], char * const dn2[]);
+int asn1_is_subject_alt_name(const uint8_t *cert, int offset);
+int asn1_is_basic_constraints(const uint8_t *cert, int offset);
+int asn1_is_key_usage(const uint8_t *cert, int offset);
+bool asn1_is_critical_ext(const uint8_t *buf, int *offset);
 #endif /* CONFIG_SSL_CERT_VERIFICATION */
 #endif /* CONFIG_SSL_CERT_VERIFICATION */
 int asn1_signature_type(const uint8_t *cert,
 int asn1_signature_type(const uint8_t *cert,
                                 int *offset, X509_CTX *x509_ctx);
                                 int *offset, X509_CTX *x509_ctx);

+ 33 - 1
myaxtls/hmac.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
+ * Copyright (c) 2007-2016, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  * 
  * 
@@ -103,3 +103,35 @@ void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
     SHA1_Update(&context, digest, SHA1_SIZE);
     SHA1_Update(&context, digest, SHA1_SIZE);
     SHA1_Final(digest, &context);
     SHA1_Final(digest, &context);
 }
 }
+/**
+ * Perform HMAC-SHA256
+ * NOTE: does not handle keys larger than the block size.
+ */
+void hmac_sha256(const uint8_t *msg, int length, const uint8_t *key, 
+        int key_len, uint8_t *digest)
+{
+    SHA256_CTX context;
+    uint8_t k_ipad[64];
+    uint8_t k_opad[64];
+    int i;
+
+    memset(k_ipad, 0, sizeof k_ipad);
+    memset(k_opad, 0, sizeof k_opad);
+    memcpy(k_ipad, key, key_len);
+    memcpy(k_opad, key, key_len);
+
+    for (i = 0; i < 64; i++) 
+    {
+        k_ipad[i] ^= 0x36;
+        k_opad[i] ^= 0x5c;
+    }
+
+    SHA256_Init(&context);
+    SHA256_Update(&context, k_ipad, 64);
+    SHA256_Update(&context, msg, length);
+    SHA256_Final(digest, &context);
+    SHA256_Init(&context);
+    SHA256_Update(&context, k_opad, 64);
+    SHA256_Update(&context, digest, SHA256_SIZE);
+    SHA256_Final(digest, &context);
+}

+ 6 - 1
myaxtls/loader.c

@@ -82,7 +82,9 @@ EXP_FUNC int LIB_CALLTYPE ssl_obj_load(SSL_CTX *ssl_ctx, int obj_type,
 #ifdef CONFIG_SSL_HAS_PEM
 #ifdef CONFIG_SSL_HAS_PEM
         ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
         ret = ssl_obj_PEM_load(ssl_ctx, obj_type, ssl_obj, password);
 #else
 #else
+#ifdef CONFIG_SSL_FULL_MODE
         printf("%s", unsupported_str);
         printf("%s", unsupported_str);
+#endif
         ret = SSL_ERROR_NOT_SUPPORTED;
         ret = SSL_ERROR_NOT_SUPPORTED;
 #endif
 #endif
     }
     }
@@ -93,7 +95,9 @@ error:
     ssl_obj_free(ssl_obj);
     ssl_obj_free(ssl_obj);
     return ret;
     return ret;
 #else
 #else
+#ifdef CONFIG_SSL_FULL_MODE
     printf("%s", unsupported_str);
     printf("%s", unsupported_str);
+#endif
     return SSL_ERROR_NOT_SUPPORTED;
     return SSL_ERROR_NOT_SUPPORTED;
 #endif /* CONFIG_SSL_SKELETON_MODE */
 #endif /* CONFIG_SSL_SKELETON_MODE */
 }
 }
@@ -150,7 +154,9 @@ static int do_obj(SSL_CTX *ssl_ctx, int obj_type,
             break;
             break;
 #endif
 #endif
         default:
         default:
+#ifdef CONFIG_SSL_FULL_MODE
             printf("%s", unsupported_str);
             printf("%s", unsupported_str);
+#endif
             ret = SSL_ERROR_NOT_SUPPORTED;
             ret = SSL_ERROR_NOT_SUPPORTED;
             break;
             break;
     }
     }
@@ -491,7 +497,6 @@ int load_key_certs_with_params(SSL_CTX *ssl_ctx,
     else if (!(options & SSL_NO_DEFAULT_KEY))
     else if (!(options & SSL_NO_DEFAULT_KEY))
     {
     {
 #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
 #if defined(CONFIG_SSL_USE_DEFAULT_KEY) || defined(CONFIG_SSL_SKELETON_MODE)
-        static const    /* saves a few bytes and RAM */
 #include "cert.h"
 #include "cert.h"
         ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT,
         ssl_obj_memory_load(ssl_ctx, SSL_OBJ_X509_CERT,
                     default_certificate, default_certificate_len, NULL);
                     default_certificate, default_certificate_len, NULL);

+ 6 - 9
myaxtls/openssl.c

@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
- *
+ * Copyright (c) 2007-2016, Cameron Rich
+ * 
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
@@ -49,10 +49,8 @@
 
 
 static char *key_password = NULL;
 static char *key_password = NULL;
 
 
-void *SSLv23_server_method(void) { return NULL; }
 void *SSLv3_server_method(void) { return NULL; }
 void *SSLv3_server_method(void) { return NULL; }
 void *TLSv1_server_method(void) { return NULL; }
 void *TLSv1_server_method(void) { return NULL; }
-void *SSLv23_client_method(void) { return NULL; }
 void *SSLv3_client_method(void) { return NULL; }
 void *SSLv3_client_method(void) { return NULL; }
 void *TLSv1_client_method(void) { return NULL; }
 void *TLSv1_client_method(void) { return NULL; }
 
 
@@ -95,14 +93,14 @@ void SSL_CTX_free(SSL_CTX * ssl_ctx)
 SSL * SSL_new(SSL_CTX *ssl_ctx)
 SSL * SSL_new(SSL_CTX *ssl_ctx)
 {
 {
     SSL *ssl;
     SSL *ssl;
-    ssl_func_type_t ssl_func_type;
+#ifdef CONFIG_SSL_ENABLE_CLIENT
+    ssl_func_type_t ssl_func_type = OPENSSL_CTX_ATTR->ssl_func_type;
+#endif
 
 
     ssl = ssl_new(ssl_ctx, -1);        /* fd is set later */
     ssl = ssl_new(ssl_ctx, -1);        /* fd is set later */
-    ssl_func_type = OPENSSL_CTX_ATTR->ssl_func_type;
 
 
 #ifdef CONFIG_SSL_ENABLE_CLIENT
 #ifdef CONFIG_SSL_ENABLE_CLIENT
-    if (ssl_func_type == SSLv23_client_method ||
-        ssl_func_type == SSLv3_client_method ||
+    if (ssl_func_type == SSLv3_client_method ||
         ssl_func_type == TLSv1_client_method)
         ssl_func_type == TLSv1_client_method)
     {
     {
         SET_SSL_FLAG(SSL_IS_CLIENT);
         SET_SSL_FLAG(SSL_IS_CLIENT);
@@ -245,7 +243,6 @@ void SSL_CTX_set_client_CA_list(SSL_CTX *ssl_ctx, void *file)
     ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, (const char *)file, NULL);
     ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CERT, (const char *)file, NULL);
 }
 }
 
 
-void SSLv23_method(void) { }
 
 
 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb) { }
 void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, void *cb) { }
 
 

+ 2 - 2
myaxtls/os_int.h

@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 2012, Cameron Rich
- *
+ * Copyright (c) 2012-2016, Cameron Rich
+ * 
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without

+ 2 - 2
myaxtls/os_port.c

@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
- *
+ * Copyright (c) 2007-2016, Cameron Rich
+ * 
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without

+ 2 - 2
myaxtls/os_port.h

@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 2007-2015, Cameron Rich
- *
+ * Copyright (c) 2007-2016, Cameron Rich
+ * 
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without

+ 3 - 3
myaxtls/p12.c

@@ -105,7 +105,7 @@ int pkcs8_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
     }
     }
 
 
     /* unencrypted key? */
     /* unencrypted key? */
-    if (asn1_get_int(buf, &offset, &version) > 0 && *version == 0)
+    if (asn1_get_big_int(buf, &offset, &version) > 0 && *version == 0)
     {
     {
         ret = p8_add_key(ssl_ctx, buf);
         ret = p8_add_key(ssl_ctx, buf);
         goto error;
         goto error;
@@ -257,7 +257,7 @@ int pkcs12_decode(SSL_CTX *ssl_ctx, SSLObjLoader *ssl_obj, const char *password)
         goto error;
         goto error;
     }
     }
 
 
-    if (asn1_get_int(buf, &offset, &version) < 0 || *version != 3)
+    if (asn1_get_big_int(buf, &offset, &version) < 0 || *version != 3)
     {
     {
         ret = SSL_ERROR_INVALID_VERSION;
         ret = SSL_ERROR_INVALID_VERSION;
         goto error;
         goto error;
@@ -463,7 +463,7 @@ static int get_pbe_params(uint8_t *buf, int *offset,
     *salt = &buf[*offset];
     *salt = &buf[*offset];
     *offset += len;
     *offset += len;
 
 
-    if ((len = asn1_get_int(buf, offset, &iter)) < 0)
+    if ((len = asn1_get_big_int(buf, offset, &iter)) < 0)
         goto error;
         goto error;
 
 
     *iterations = 0;
     *iterations = 0;

+ 3 - 0
myaxtls/rc4.c

@@ -37,6 +37,8 @@
 #include "os_port.h"
 #include "os_port.h"
 #include "crypto.h"
 #include "crypto.h"
 
 
+/* only used for PKCS12 now */
+#ifdef CONFIG_SSL_USE_PKCS12
 /**
 /**
  * Get ready for an encrypt/decrypt operation
  * Get ready for an encrypt/decrypt operation
  */
  */
@@ -90,3 +92,4 @@ void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
     ctx->x = x;
     ctx->x = x;
     ctx->y = y;
     ctx->y = y;
 }
 }
+#endif

+ 8 - 8
myaxtls/sha384.c

@@ -38,14 +38,14 @@
  void SHA384_Init(SHA384_CTX *ctx)
  void SHA384_Init(SHA384_CTX *ctx)
  {
  {
     //Set initial hash value
     //Set initial hash value
-    ctx->h_dig.h[0] = 0xCBBB9D5DC1059ED8;
-    ctx->h_dig.h[1] = 0x629A292A367CD507;
-    ctx->h_dig.h[2] = 0x9159015A3070DD17;
-    ctx->h_dig.h[3] = 0x152FECD8F70E5939;
-    ctx->h_dig.h[4] = 0x67332667FFC00B31;
-    ctx->h_dig.h[5] = 0x8EB44A8768581511;
-    ctx->h_dig.h[6] = 0xDB0C2E0D64F98FA7;
-    ctx->h_dig.h[7] = 0x47B5481DBEFA4FA4;
+    ctx->h_dig.h[0] = 0xCBBB9D5DC1059ED8LL;
+    ctx->h_dig.h[1] = 0x629A292A367CD507LL;
+    ctx->h_dig.h[2] = 0x9159015A3070DD17LL;
+    ctx->h_dig.h[3] = 0x152FECD8F70E5939LL;
+    ctx->h_dig.h[4] = 0x67332667FFC00B31LL;
+    ctx->h_dig.h[5] = 0x8EB44A8768581511LL;
+    ctx->h_dig.h[6] = 0xDB0C2E0D64F98FA7LL;
+    ctx->h_dig.h[7] = 0x47B5481DBEFA4FA4LL;
  
  
     // Number of bytes in the buffer
     // Number of bytes in the buffer
     ctx->size = 0;
     ctx->size = 0;

+ 28 - 28
myaxtls/sha512.c

@@ -56,26 +56,26 @@ static const uint8_t padding[128] =
  
  
 static const uint64_t k[80] =
 static const uint64_t k[80] =
 {
 {
-    0x428A2F98D728AE22, 0x7137449123EF65CD, 0xB5C0FBCFEC4D3B2F, 0xE9B5DBA58189DBBC,
-    0x3956C25BF348B538, 0x59F111F1B605D019, 0x923F82A4AF194F9B, 0xAB1C5ED5DA6D8118,
-    0xD807AA98A3030242, 0x12835B0145706FBE, 0x243185BE4EE4B28C, 0x550C7DC3D5FFB4E2,
-    0x72BE5D74F27B896F, 0x80DEB1FE3B1696B1, 0x9BDC06A725C71235, 0xC19BF174CF692694,
-    0xE49B69C19EF14AD2, 0xEFBE4786384F25E3, 0x0FC19DC68B8CD5B5, 0x240CA1CC77AC9C65,
-    0x2DE92C6F592B0275, 0x4A7484AA6EA6E483, 0x5CB0A9DCBD41FBD4, 0x76F988DA831153B5,
-    0x983E5152EE66DFAB, 0xA831C66D2DB43210, 0xB00327C898FB213F, 0xBF597FC7BEEF0EE4,
-    0xC6E00BF33DA88FC2, 0xD5A79147930AA725, 0x06CA6351E003826F, 0x142929670A0E6E70,
-    0x27B70A8546D22FFC, 0x2E1B21385C26C926, 0x4D2C6DFC5AC42AED, 0x53380D139D95B3DF,
-    0x650A73548BAF63DE, 0x766A0ABB3C77B2A8, 0x81C2C92E47EDAEE6, 0x92722C851482353B,
-    0xA2BFE8A14CF10364, 0xA81A664BBC423001, 0xC24B8B70D0F89791, 0xC76C51A30654BE30,
-    0xD192E819D6EF5218, 0xD69906245565A910, 0xF40E35855771202A, 0x106AA07032BBD1B8,
-    0x19A4C116B8D2D0C8, 0x1E376C085141AB53, 0x2748774CDF8EEB99, 0x34B0BCB5E19B48A8,
-    0x391C0CB3C5C95A63, 0x4ED8AA4AE3418ACB, 0x5B9CCA4F7763E373, 0x682E6FF3D6B2B8A3,
-    0x748F82EE5DEFB2FC, 0x78A5636F43172F60, 0x84C87814A1F0AB72, 0x8CC702081A6439EC,
-    0x90BEFFFA23631E28, 0xA4506CEBDE82BDE9, 0xBEF9A3F7B2C67915, 0xC67178F2E372532B,
-    0xCA273ECEEA26619C, 0xD186B8C721C0C207, 0xEADA7DD6CDE0EB1E, 0xF57D4F7FEE6ED178,
-    0x06F067AA72176FBA, 0x0A637DC5A2C898A6, 0x113F9804BEF90DAE, 0x1B710B35131C471B,
-    0x28DB77F523047D84, 0x32CAAB7B40C72493, 0x3C9EBE0A15C9BEBC, 0x431D67C49C100D4C,
-    0x4CC5D4BECB3E42B6, 0x597F299CFC657E2A, 0x5FCB6FAB3AD6FAEC, 0x6C44198C4A475817
+    0x428A2F98D728AE22LL, 0x7137449123EF65CDLL, 0xB5C0FBCFEC4D3B2FLL, 0xE9B5DBA58189DBBCLL,
+    0x3956C25BF348B538LL, 0x59F111F1B605D019LL, 0x923F82A4AF194F9BLL, 0xAB1C5ED5DA6D8118LL,
+    0xD807AA98A3030242LL, 0x12835B0145706FBELL, 0x243185BE4EE4B28CLL, 0x550C7DC3D5FFB4E2LL,
+    0x72BE5D74F27B896FLL, 0x80DEB1FE3B1696B1LL, 0x9BDC06A725C71235LL, 0xC19BF174CF692694LL,
+    0xE49B69C19EF14AD2LL, 0xEFBE4786384F25E3LL, 0x0FC19DC68B8CD5B5LL, 0x240CA1CC77AC9C65LL,
+    0x2DE92C6F592B0275LL, 0x4A7484AA6EA6E483LL, 0x5CB0A9DCBD41FBD4LL, 0x76F988DA831153B5LL,
+    0x983E5152EE66DFABLL, 0xA831C66D2DB43210LL, 0xB00327C898FB213FLL, 0xBF597FC7BEEF0EE4LL,
+    0xC6E00BF33DA88FC2LL, 0xD5A79147930AA725LL, 0x06CA6351E003826FLL, 0x142929670A0E6E70LL,
+    0x27B70A8546D22FFCLL, 0x2E1B21385C26C926LL, 0x4D2C6DFC5AC42AEDLL, 0x53380D139D95B3DFLL,
+    0x650A73548BAF63DELL, 0x766A0ABB3C77B2A8LL, 0x81C2C92E47EDAEE6LL, 0x92722C851482353BLL,
+    0xA2BFE8A14CF10364LL, 0xA81A664BBC423001LL, 0xC24B8B70D0F89791LL, 0xC76C51A30654BE30LL,
+    0xD192E819D6EF5218LL, 0xD69906245565A910LL, 0xF40E35855771202ALL, 0x106AA07032BBD1B8LL,
+    0x19A4C116B8D2D0C8LL, 0x1E376C085141AB53LL, 0x2748774CDF8EEB99LL, 0x34B0BCB5E19B48A8LL,
+    0x391C0CB3C5C95A63LL, 0x4ED8AA4AE3418ACBLL, 0x5B9CCA4F7763E373LL, 0x682E6FF3D6B2B8A3LL,
+    0x748F82EE5DEFB2FCLL, 0x78A5636F43172F60LL, 0x84C87814A1F0AB72LL, 0x8CC702081A6439ECLL,
+    0x90BEFFFA23631E28LL, 0xA4506CEBDE82BDE9LL, 0xBEF9A3F7B2C67915LL, 0xC67178F2E372532BLL,
+    0xCA273ECEEA26619CLL, 0xD186B8C721C0C207LL, 0xEADA7DD6CDE0EB1ELL, 0xF57D4F7FEE6ED178LL,
+    0x06F067AA72176FBALL, 0x0A637DC5A2C898A6LL, 0x113F9804BEF90DAELL, 0x1B710B35131C471BLL,
+    0x28DB77F523047D84LL, 0x32CAAB7B40C72493LL, 0x3C9EBE0A15C9BEBCLL, 0x431D67C49C100D4CLL,
+    0x4CC5D4BECB3E42B6LL, 0x597F299CFC657E2ALL, 0x5FCB6FAB3AD6FAECLL, 0x6C44198C4A475817LL
 };
 };
  
  
 /**
 /**
@@ -83,14 +83,14 @@ static const uint64_t k[80] =
 */
 */
 void SHA512_Init(SHA512_CTX *ctx)
 void SHA512_Init(SHA512_CTX *ctx)
 {
 {
-    ctx->h_dig.h[0] = 0x6A09E667F3BCC908;
-    ctx->h_dig.h[1] = 0xBB67AE8584CAA73B;
-    ctx->h_dig.h[2] = 0x3C6EF372FE94F82B;
-    ctx->h_dig.h[3] = 0xA54FF53A5F1D36F1;
-    ctx->h_dig.h[4] = 0x510E527FADE682D1;
-    ctx->h_dig.h[5] = 0x9B05688C2B3E6C1F;
-    ctx->h_dig.h[6] = 0x1F83D9ABFB41BD6B;
-    ctx->h_dig.h[7] = 0x5BE0CD19137E2179;
+    ctx->h_dig.h[0] = 0x6A09E667F3BCC908LL;
+    ctx->h_dig.h[1] = 0xBB67AE8584CAA73BLL;
+    ctx->h_dig.h[2] = 0x3C6EF372FE94F82BLL;
+    ctx->h_dig.h[3] = 0xA54FF53A5F1D36F1LL;
+    ctx->h_dig.h[4] = 0x510E527FADE682D1LL;
+    ctx->h_dig.h[5] = 0x9B05688C2B3E6C1FLL;
+    ctx->h_dig.h[6] = 0x1F83D9ABFB41BD6BLL;
+    ctx->h_dig.h[7] = 0x5BE0CD19137E2179LL;
     ctx->size = 0;
     ctx->size = 0;
     ctx->totalSize = 0;
     ctx->totalSize = 0;
 }
 }

+ 42 - 17
myaxtls/ssl.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
+ * Copyright (c) 2007-2016, Cameron Rich
  *
  *
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -71,20 +71,21 @@ extern "C" {
 
 
 /* need to predefine before ssl_lib.h gets to it */
 /* need to predefine before ssl_lib.h gets to it */
 #define SSL_SESSION_ID_SIZE                     32
 #define SSL_SESSION_ID_SIZE                     32
-
-#ifdef SSL_STATIC_LIBRARY
-#define EXP_FUNC
-#define LIB_CALLTYPE
-#endif
+
+#ifdef SSL_STATIC_LIBRARY
+#define EXP_FUNC
+#define LIB_CALLTYPE
+#endif
 
 
 #ifdef AXTLS_LIBRARY
 #ifdef AXTLS_LIBRARY
 #include "tls1.h"
 #include "tls1.h"
-#else
-#ifdef __GNUC__
-#include <stdint.h>
+#else
+#ifdef __GNUC__
+#include <stdint.h>
 #endif
 #endif
 typedef struct SSL_CTX SSL_CTX;
 typedef struct SSL_CTX SSL_CTX;
 typedef struct SSL SSL;
 typedef struct SSL SSL;
+typedef struct SSL_EXTENSIONS SSL_EXTENSIONS;
 #endif
 #endif
 
 
 /* The optional parameters that can be given to the client/server SSL engine */
 /* The optional parameters that can be given to the client/server SSL engine */
@@ -103,13 +104,16 @@ typedef struct SSL SSL;
 #define SSL_ERROR_DEAD                          -2
 #define SSL_ERROR_DEAD                          -2
 #define SSL_CLOSE_NOTIFY                        -3
 #define SSL_CLOSE_NOTIFY                        -3
 #define SSL_ERROR_CONN_LOST                     -256
 #define SSL_ERROR_CONN_LOST                     -256
+#define SSL_ERROR_RECORD_OVERFLOW               -257
 #define SSL_ERROR_SOCK_SETUP_FAILURE            -258
 #define SSL_ERROR_SOCK_SETUP_FAILURE            -258
 #define SSL_ERROR_INVALID_HANDSHAKE             -260
 #define SSL_ERROR_INVALID_HANDSHAKE             -260
 #define SSL_ERROR_INVALID_PROT_MSG              -261
 #define SSL_ERROR_INVALID_PROT_MSG              -261
 #define SSL_ERROR_INVALID_HMAC                  -262
 #define SSL_ERROR_INVALID_HMAC                  -262
 #define SSL_ERROR_INVALID_VERSION               -263
 #define SSL_ERROR_INVALID_VERSION               -263
+#define SSL_ERROR_UNSUPPORTED_EXTENSION         -264
 #define SSL_ERROR_INVALID_SESSION               -265
 #define SSL_ERROR_INVALID_SESSION               -265
 #define SSL_ERROR_NO_CIPHER                     -266
 #define SSL_ERROR_NO_CIPHER                     -266
+#define SSL_ERROR_INVALID_CERT_HASH_ALG         -267
 #define SSL_ERROR_BAD_CERTIFICATE               -268
 #define SSL_ERROR_BAD_CERTIFICATE               -268
 #define SSL_ERROR_INVALID_KEY                   -269
 #define SSL_ERROR_INVALID_KEY                   -269
 #define SSL_ERROR_FINISHED_INVALID              -271
 #define SSL_ERROR_FINISHED_INVALID              -271
@@ -127,19 +131,25 @@ typedef struct SSL SSL;
 #define SSL_ALERT_CLOSE_NOTIFY                  0
 #define SSL_ALERT_CLOSE_NOTIFY                  0
 #define SSL_ALERT_UNEXPECTED_MESSAGE            10
 #define SSL_ALERT_UNEXPECTED_MESSAGE            10
 #define SSL_ALERT_BAD_RECORD_MAC                20
 #define SSL_ALERT_BAD_RECORD_MAC                20
+#define SSL_ALERT_RECORD_OVERFLOW               22
 #define SSL_ALERT_HANDSHAKE_FAILURE             40
 #define SSL_ALERT_HANDSHAKE_FAILURE             40
 #define SSL_ALERT_BAD_CERTIFICATE               42
 #define SSL_ALERT_BAD_CERTIFICATE               42
+#define SSL_ALERT_UNSUPPORTED_CERTIFICATE       43
+#define SSL_ALERT_CERTIFICATE_EXPIRED           45
+#define SSL_ALERT_CERTIFICATE_UNKNOWN           46
 #define SSL_ALERT_ILLEGAL_PARAMETER             47
 #define SSL_ALERT_ILLEGAL_PARAMETER             47
+#define SSL_ALERT_UNKNOWN_CA                    48
 #define SSL_ALERT_DECODE_ERROR                  50
 #define SSL_ALERT_DECODE_ERROR                  50
 #define SSL_ALERT_DECRYPT_ERROR                 51
 #define SSL_ALERT_DECRYPT_ERROR                 51
 #define SSL_ALERT_INVALID_VERSION               70
 #define SSL_ALERT_INVALID_VERSION               70
 #define SSL_ALERT_NO_RENEGOTIATION              100
 #define SSL_ALERT_NO_RENEGOTIATION              100
+#define SSL_ALERT_UNSUPPORTED_EXTENSION         110
 
 
 /* The ciphers that are supported */
 /* The ciphers that are supported */
 #define SSL_AES128_SHA                          0x2f
 #define SSL_AES128_SHA                          0x2f
 #define SSL_AES256_SHA                          0x35
 #define SSL_AES256_SHA                          0x35
-#define SSL_RC4_128_SHA                         0x05
-#define SSL_RC4_128_MD5                         0x04
+#define SSL_AES128_SHA256                       0x3c
+#define SSL_AES256_SHA256                       0x3d
 
 
 /* build mode ids' */
 /* build mode ids' */
 #define SSL_BUILD_SKELETON_MODE                 0x01
 #define SSL_BUILD_SKELETON_MODE                 0x01
@@ -162,9 +172,15 @@ typedef struct SSL SSL;
 #define SSL_X509_CERT_COMMON_NAME               0
 #define SSL_X509_CERT_COMMON_NAME               0
 #define SSL_X509_CERT_ORGANIZATION              1
 #define SSL_X509_CERT_ORGANIZATION              1
 #define SSL_X509_CERT_ORGANIZATIONAL_NAME       2
 #define SSL_X509_CERT_ORGANIZATIONAL_NAME       2
-#define SSL_X509_CA_CERT_COMMON_NAME            3
-#define SSL_X509_CA_CERT_ORGANIZATION           4
-#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME    5
+#define SSL_X509_CERT_LOCATION                  3
+#define SSL_X509_CERT_COUNTRY                   4
+#define SSL_X509_CERT_STATE                     5
+#define SSL_X509_CA_CERT_COMMON_NAME            6
+#define SSL_X509_CA_CERT_ORGANIZATION           7
+#define SSL_X509_CA_CERT_ORGANIZATIONAL_NAME    8
+#define SSL_X509_CA_CERT_LOCATION               9
+#define SSL_X509_CA_CERT_COUNTRY                10
+#define SSL_X509_CA_CERT_STATE                  11
 
 
 /* SSL object loader types */
 /* SSL object loader types */
 #define SSL_OBJ_X509_CERT                       1
 #define SSL_OBJ_X509_CERT                       1
@@ -262,10 +278,13 @@ EXP_FUNC SSL * LIB_CALLTYPE ssl_server_new(SSL_CTX *ssl_ctx, int client_fd);
  * can be null if no session resumption is being used or required. This option
  * can be null if no session resumption is being used or required. This option
  * is not used in skeleton mode.
  * is not used in skeleton mode.
  * @param sess_id_size The size of the session id (max 32)
  * @param sess_id_size The size of the session id (max 32)
+ * @param ssl_ext pointer to a structure with the activated SSL extensions
+ * and their values
  * @return An SSL object reference. Use ssl_handshake_status() to check
  * @return An SSL object reference. Use ssl_handshake_status() to check
  * if a handshake succeeded.
  * if a handshake succeeded.
  */
  */
-EXP_FUNC SSL * LIB_CALLTYPE ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id, uint8_t sess_id_size);
+EXP_FUNC SSL * LIB_CALLTYPE ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const uint8_t *session_id,
+                                           uint8_t sess_id_size, SSL_EXTENSIONS* ssl_ext);
 
 
 /**
 /**
  * @brief Free any used resources on this connection.
  * @brief Free any used resources on this connection.
@@ -344,8 +363,8 @@ EXP_FUNC uint8_t LIB_CALLTYPE ssl_get_session_id_size(const SSL *ssl);
  * @return The cipher id. This will be one of the following:
  * @return The cipher id. This will be one of the following:
  * - SSL_AES128_SHA (0x2f)
  * - SSL_AES128_SHA (0x2f)
  * - SSL_AES256_SHA (0x35)
  * - SSL_AES256_SHA (0x35)
- * - SSL_RC4_128_SHA (0x05)
- * - SSL_RC4_128_MD5 (0x04)
+ * - SSL_AES128_SHA256 (0x3c)
+ * - SSL_AES256_SHA256 (0x3d)
  */
  */
 EXP_FUNC uint8_t LIB_CALLTYPE ssl_get_cipher_id(const SSL *ssl);
 EXP_FUNC uint8_t LIB_CALLTYPE ssl_get_cipher_id(const SSL *ssl);
 
 
@@ -407,9 +426,15 @@ EXP_FUNC int LIB_CALLTYPE ssl_verify_cert(const SSL *ssl);
  * - SSL_X509_CERT_COMMON_NAME
  * - SSL_X509_CERT_COMMON_NAME
  * - SSL_X509_CERT_ORGANIZATION
  * - SSL_X509_CERT_ORGANIZATION
  * - SSL_X509_CERT_ORGANIZATIONAL_NAME
  * - SSL_X509_CERT_ORGANIZATIONAL_NAME
+ * - SSL_X509_CERT_LOCATION
+ * - SSL_X509_CERT_COUNTRY
+ * - SSL_X509_CERT_STATE
  * - SSL_X509_CA_CERT_COMMON_NAME
  * - SSL_X509_CA_CERT_COMMON_NAME
  * - SSL_X509_CA_CERT_ORGANIZATION
  * - SSL_X509_CA_CERT_ORGANIZATION
  * - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
  * - SSL_X509_CA_CERT_ORGANIZATIONAL_NAME
+ * - SSL_X509_CA_CERT_LOCATION
+ * - SSL_X509_CA_CERT_COUNTRY
+ * - SSL_X509_CA_CERT_STATE
  * @return The appropriate string (or null if not defined)
  * @return The appropriate string (or null if not defined)
  * @note Verification build mode must be enabled.
  * @note Verification build mode must be enabled.
  */
  */

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 385 - 205
myaxtls/tls1.c


+ 42 - 19
myaxtls/tls1.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007-2014, Cameron Rich
+ * Copyright (c) 2007-2016, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -43,13 +43,14 @@ extern "C" {
 #include "version.h"
 #include "version.h"
 #include "config.h"
 #include "config.h"
 #include "os_int.h"
 #include "os_int.h"
+#include "os_port.h"
 #include "crypto.h"
 #include "crypto.h"
 #include "crypto_misc.h"
 #include "crypto_misc.h"
 
 
 #define SSL_PROTOCOL_MIN_VERSION    0x31   /* TLS v1.0 */
 #define SSL_PROTOCOL_MIN_VERSION    0x31   /* TLS v1.0 */
-#define SSL_PROTOCOL_MINOR_VERSION  0x02   /* TLS v1.1 */
-#define SSL_PROTOCOL_VERSION_MAX    0x32   /* TLS v1.1 */
-#define SSL_PROTOCOL_VERSION1_1     0x32   /* TLS v1.1 */
+#define SSL_PROTOCOL_VERSION_MAX    0x33   /* TLS v1.3 */
+#define SSL_PROTOCOL_VERSION_TLS1_1 0x32   /* TLS v1.1 */
+#define SSL_PROTOCOL_VERSION_TLS1_2 0x33   /* TLS v1.2 */
 #define SSL_RANDOM_SIZE             32
 #define SSL_RANDOM_SIZE             32
 #define SSL_SECRET_SIZE             48
 #define SSL_SECRET_SIZE             48
 #define SSL_FINISHED_HASH_SIZE      12
 #define SSL_FINISHED_HASH_SIZE      12
@@ -76,16 +77,17 @@ extern "C" {
 
 
 #define MAX_KEY_BYTE_SIZE           512     /* for a 4096 bit key */
 #define MAX_KEY_BYTE_SIZE           512     /* for a 4096 bit key */
 
 
-/*then values bellow should not sum up more than what can be stored on uint16_t*/
 #define RT_MAX_PLAIN_LENGTH         16384
 #define RT_MAX_PLAIN_LENGTH         16384
 #define RT_EXTRA                    1024
 #define RT_EXTRA                    1024
 #define BM_RECORD_OFFSET            5
 #define BM_RECORD_OFFSET            5
 
 
-#ifdef CONFIG_SSL_SKELETON_MODE
-#define NUM_PROTOCOLS               1
-#else
 #define NUM_PROTOCOLS               4
 #define NUM_PROTOCOLS               4
-#endif
+#define MAX_SIG_ALGORITHMS          4
+#define SIG_ALG_SHA1                2
+#define SIG_ALG_SHA256              4
+#define SIG_ALG_SHA384              5
+#define SIG_ALG_SHA512              6
+#define SIG_ALG_RSA                 1
 
 
 #define PARANOIA_CHECK(A, B)        if (A < B) { \
 #define PARANOIA_CHECK(A, B)        if (A < B) { \
     ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
     ret = SSL_ERROR_INVALID_HANDSHAKE; goto error; }
@@ -114,14 +116,22 @@ enum
     HS_FINISHED = 20
     HS_FINISHED = 20
 };
 };
 
 
+/* SSL extension types */
+enum
+{
+    SSL_EXT_SERVER_NAME = 0,
+    SSL_EXT_MAX_FRAGMENT_SIZE,
+    SSL_EXT_SIG_ALG = 0x0d,
+};
+
 typedef struct
 typedef struct
 {
 {
     uint8_t cipher;
     uint8_t cipher;
     uint8_t key_size;
     uint8_t key_size;
     uint8_t iv_size;
     uint8_t iv_size;
-    uint8_t key_block_size;
     uint8_t padding_size;
     uint8_t padding_size;
     uint8_t digest_size;
     uint8_t digest_size;
+    uint8_t key_block_size;
     hmac_func hmac;
     hmac_func hmac;
     crypt_func encrypt;
     crypt_func encrypt;
     crypt_func decrypt;
     crypt_func decrypt;
@@ -146,20 +156,30 @@ typedef struct
 {
 {
     uint8_t *buf;
     uint8_t *buf;
     int size;
     int size;
+    uint8_t hash_alg;
 } SSL_CERT;
 } SSL_CERT;
 
 
 typedef struct
 typedef struct
 {
 {
     MD5_CTX md5_ctx;
     MD5_CTX md5_ctx;
     SHA1_CTX sha1_ctx;
     SHA1_CTX sha1_ctx;
-    uint8_t final_finish_mac[SSL_FINISHED_HASH_SIZE];
-    uint8_t *key_block;
-    uint8_t master_secret[SSL_SECRET_SIZE];
+    SHA256_CTX sha256_ctx;
     uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
     uint8_t client_random[SSL_RANDOM_SIZE]; /* client's random sequence */
     uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
     uint8_t server_random[SSL_RANDOM_SIZE]; /* server's random sequence */
+    uint8_t final_finish_mac[128];
+    uint8_t master_secret[SSL_SECRET_SIZE];
+    uint8_t key_block[256];
     uint16_t bm_proc_index;
     uint16_t bm_proc_index;
+    uint8_t key_block_generated;
 } DISPOSABLE_CTX;
 } DISPOSABLE_CTX;
 
 
+typedef struct 
+{
+    const char *host_name; /* Needed for the SNI support */
+    /* Needed for the Max Fragment Size Extension. 
+       Allowed values: 2^9, 2^10 .. 2^14 */
+    uint16_t max_fragment_size; 
+} SSL_EXTENSIONS;
 struct _SSL
 struct _SSL
 {
 {
     uint32_t flag;
     uint32_t flag;
@@ -187,6 +207,8 @@ struct _SSL
 
 
     uint16_t bm_index;
     uint16_t bm_index;
     uint16_t bm_read_index;
     uint16_t bm_read_index;
+    uint8_t sig_algs[MAX_SIG_ALGORITHMS];
+    uint8_t num_sig_algs;
     struct _SSL *next;                  /* doubly linked list */
     struct _SSL *next;                  /* doubly linked list */
     struct _SSL *prev;
     struct _SSL *prev;
     struct _SSL_CTX *ssl_ctx;           /* back reference to a clnt/svr ctx */
     struct _SSL_CTX *ssl_ctx;           /* back reference to a clnt/svr ctx */
@@ -198,12 +220,13 @@ struct _SSL
     X509_CTX *x509_ctx;
     X509_CTX *x509_ctx;
 #endif
 #endif
 
 
-    uint8_t session_id[SSL_SESSION_ID_SIZE];
-    uint8_t client_mac[SHA1_SIZE];  /* for HMAC verification */
-    uint8_t server_mac[SHA1_SIZE];  /* for HMAC verification */
-    uint8_t read_sequence[8];       /* 64 bit sequence number */
-    uint8_t write_sequence[8];      /* 64 bit sequence number */
+    uint8_t session_id[SSL_SESSION_ID_SIZE]; 
+    uint8_t client_mac[SHA256_SIZE];    /* for HMAC verification */
+    uint8_t server_mac[SHA256_SIZE];    /* for HMAC verification */
+    uint8_t read_sequence[8];           /* 64 bit sequence number */
+    uint8_t write_sequence[8];          /* 64 bit sequence number */
     uint8_t hmac_header[SSL_RECORD_SIZE];    /* rx hmac */
     uint8_t hmac_header[SSL_RECORD_SIZE];    /* rx hmac */
+    SSL_EXTENSIONS *extensions; /* Contains the SSL (client) extensions */
 };
 };
 
 
 typedef struct _SSL SSL;
 typedef struct _SSL SSL;
@@ -252,7 +275,7 @@ int send_finished(SSL *ssl);
 int send_certificate(SSL *ssl);
 int send_certificate(SSL *ssl);
 int basic_read(SSL *ssl, uint8_t **in_data, int in_num);
 int basic_read(SSL *ssl, uint8_t **in_data, int in_num);
 int send_change_cipher_spec(SSL *ssl);
 int send_change_cipher_spec(SSL *ssl);
-void finished_digest(SSL *ssl, const char *label, uint8_t *digest);
+int finished_digest(SSL *ssl, const char *label, uint8_t *digest);
 void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
 void generate_master_secret(SSL *ssl, const uint8_t *premaster_secret);
 void add_packet(SSL *ssl, const uint8_t *pkt, int len);
 void add_packet(SSL *ssl, const uint8_t *pkt, int len);
 int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);
 int add_cert(SSL_CTX *ssl_ctx, const uint8_t *buf, int len);

+ 151 - 18
myaxtls/tls1_clnt.c

@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
- *
+ * Copyright (c) 2007-2016, Cameron Rich
+ * 
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,21 @@
 
 
 #ifdef CONFIG_SSL_ENABLE_CLIENT        /* all commented out if no client */
 #ifdef CONFIG_SSL_ENABLE_CLIENT        /* all commented out if no client */
 
 
+/* support sha512/384/256/1 RSA */
+static const uint8_t g_sig_alg[] = { 
+                0x00, SSL_EXT_SIG_ALG,
+                0x00, 0x0a, 0x00, 0x08,
+                SIG_ALG_SHA512, SIG_ALG_RSA,
+                SIG_ALG_SHA384, SIG_ALG_RSA,
+                SIG_ALG_SHA256, SIG_ALG_RSA,
+                SIG_ALG_SHA1, SIG_ALG_RSA 
+};
+
+static const uint8_t g_asn1_sha256[] = 
+{ 
+    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 
+    0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+};
 static int send_client_hello(SSL *ssl);
 static int send_client_hello(SSL *ssl);
 static int process_server_hello(SSL *ssl);
 static int process_server_hello(SSL *ssl);
 static int process_server_hello_done(SSL *ssl);
 static int process_server_hello_done(SSL *ssl);
@@ -48,7 +63,7 @@ static int send_cert_verify(SSL *ssl);
  * Establish a new SSL connection to an SSL server.
  * Establish a new SSL connection to an SSL server.
  */
  */
 EXP_FUNC SSL * LIB_CALLTYPE ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
 EXP_FUNC SSL * LIB_CALLTYPE ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, const
-        uint8_t *session_id, uint8_t sess_id_size)
+        uint8_t *session_id, uint8_t sess_id_size, SSL_EXTENSIONS* ssl_ext)
 {
 {
     SSL *ssl = ssl_new(ssl_ctx, client_fd);
     SSL *ssl = ssl_new(ssl_ctx, client_fd);
     ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */
     ssl->version = SSL_PROTOCOL_VERSION_MAX; /* try top version first */
@@ -66,6 +81,7 @@ EXP_FUNC SSL * LIB_CALLTYPE ssl_client_new(SSL_CTX *ssl_ctx, int client_fd, cons
         SET_SSL_FLAG(SSL_SESSION_RESUME);   /* just flag for later */
         SET_SSL_FLAG(SSL_SESSION_RESUME);   /* just flag for later */
     }
     }
 
 
+    ssl->extensions = ssl_ext;
     SET_SSL_FLAG(SSL_IS_CLIENT);
     SET_SSL_FLAG(SSL_IS_CLIENT);
     do_client_connect(ssl);
     do_client_connect(ssl);
     return ssl;
     return ssl;
@@ -173,7 +189,8 @@ static int send_client_hello(SSL *ssl)
     uint8_t *buf = ssl->bm_data;
     uint8_t *buf = ssl->bm_data;
     time_t tm = time(NULL);
     time_t tm = time(NULL);
     uint8_t *tm_ptr = &buf[6]; /* time will go here */
     uint8_t *tm_ptr = &buf[6]; /* time will go here */
-    int i, offset;
+    int i, offset, ext_offset;
+    int ext_len = 0;
 
 
     buf[0] = HS_CLIENT_HELLO;
     buf[0] = HS_CLIENT_HELLO;
     buf[1] = 0;
     buf[1] = 0;
@@ -219,8 +236,64 @@ static int send_client_hello(SSL *ssl)
 
 
     buf[offset++] = 1;              /* no compression */
     buf[offset++] = 1;              /* no compression */
     buf[offset++] = 0;
     buf[offset++] = 0;
-    buf[3] = offset - 4;            /* handshake size */
 
 
+    ext_offset = offset;
+
+    buf[offset++] = 0;              /* total length of extensions */
+    buf[offset++] = 0;
+
+    /* send the signature algorithm extension for TLS 1.2+ */
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2)
+    {
+        memcpy(&buf[offset], g_sig_alg, sizeof(g_sig_alg));
+        offset += sizeof(g_sig_alg);
+        ext_len += sizeof(g_sig_alg);
+    }
+
+    if (ssl->extensions != NULL) 
+    {
+        /* send the host name if specified */
+        if (ssl->extensions->host_name != NULL) 
+        {
+            size_t host_len = strlen(ssl->extensions->host_name);
+            buf[offset++] = 0;
+            buf[offset++] = SSL_EXT_SERVER_NAME; /* server_name(0) (65535) */
+            buf[offset++] = 0;
+            buf[offset++] = host_len + 5; /* server_name length */
+            buf[offset++] = 0;
+            buf[offset++] = host_len + 3; /* server_list length */
+            buf[offset++] = 0; /* host_name(0) (255) */
+            buf[offset++] = 0;
+            buf[offset++] = host_len; /* host_name length */
+            strncpy((char*) &buf[offset], ssl->extensions->host_name, host_len);
+            offset += host_len;
+            ext_len += host_len + 9;
+        }
+
+        if (ssl->extensions->max_fragment_size) 
+        {
+            buf[offset++] = 0;
+            buf[offset++] = SSL_EXT_MAX_FRAGMENT_SIZE;
+
+            buf[offset++] = 0; // size of data
+            buf[offset++] = 2;
+
+            buf[offset++] = (uint8_t)
+                ((ssl->extensions->max_fragment_size >> 8) & 0xff);
+            buf[offset++] = (uint8_t)
+                (ssl->extensions->max_fragment_size & 0xff);
+            ext_len += 6;
+        }
+    }
+
+    if (ext_len > 0) 
+    {
+    	// update the extensions length value
+    	buf[ext_offset] = (uint8_t) ((ext_len >> 8) & 0xff);
+    	buf[ext_offset + 1] = (uint8_t) (ext_len & 0xff);
+    }
+
+    buf[3] = offset - 4;            /* handshake size */
     return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
     return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
 }
 }
 
 
@@ -279,15 +352,18 @@ static int process_server_hello(SSL *ssl)
     ssl->sess_id_size = sess_id_size;
     ssl->sess_id_size = sess_id_size;
     offset += sess_id_size;
     offset += sess_id_size;
 
 
-    /* get the real cipher we are using */
+    /* get the real cipher we are using - ignore MSB */
     ssl->cipher = buf[++offset];
     ssl->cipher = buf[++offset];
     ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ?
     ssl->next_state = IS_SET_SSL_FLAG(SSL_SESSION_RESUME) ?
                                         HS_FINISHED : HS_CERTIFICATE;
                                         HS_FINISHED : HS_CERTIFICATE;
 
 
-    offset++;   // skip the compr
+    offset += 2; // ignore compression
     PARANOIA_CHECK(pkt_size, offset);
     PARANOIA_CHECK(pkt_size, offset);
-    ssl->dc->bm_proc_index = offset+1;
 
 
+    ssl->dc->bm_proc_index = offset; 
+    PARANOIA_CHECK(pkt_size, offset);
+
+    // no extensions
 error:
 error:
     return ret;
     return ret;
 }
 }
@@ -313,8 +389,10 @@ static int send_client_key_xchg(SSL *ssl)
     buf[0] = HS_CLIENT_KEY_XCHG;
     buf[0] = HS_CLIENT_KEY_XCHG;
     buf[1] = 0;
     buf[1] = 0;
 
 
-    premaster_secret[0] = 0x03; /* encode the version number */
-    premaster_secret[1] = SSL_PROTOCOL_MINOR_VERSION; /* must be TLS 1.1 */
+    // spec says client must use the what is initially negotiated -
+    // and this is our current version
+    premaster_secret[0] = 0x03; 
+    premaster_secret[1] = SSL_PROTOCOL_VERSION_MAX & 0x0f; 
     if (get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]) < 0)
     if (get_random(SSL_SECRET_SIZE-2, &premaster_secret[2]) < 0)
         return SSL_NOT_OK;
         return SSL_NOT_OK;
 
 
@@ -342,14 +420,45 @@ static int process_cert_req(SSL *ssl)
 {
 {
     uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
     uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
     int ret = SSL_OK;
     int ret = SSL_OK;
-    int offset = (buf[2] << 4) + buf[3];
+    int cert_req_size = (buf[2]<<8) + buf[3];
+    int offset = 4;
     int pkt_size = ssl->bm_index;
     int pkt_size = ssl->bm_index;
+    uint8_t cert_type_len, sig_alg_len;
+
+    PARANOIA_CHECK(pkt_size, offset + cert_req_size);
+    ssl->dc->bm_proc_index = cert_req_size;
 
 
     /* don't do any processing - we will send back an RSA certificate anyway */
     /* don't do any processing - we will send back an RSA certificate anyway */
     ssl->next_state = HS_SERVER_HELLO_DONE;
     ssl->next_state = HS_SERVER_HELLO_DONE;
     SET_SSL_FLAG(SSL_HAS_CERT_REQ);
     SET_SSL_FLAG(SSL_HAS_CERT_REQ);
-    ssl->dc->bm_proc_index += offset;
-    PARANOIA_CHECK(pkt_size, offset);
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
+    {
+        // supported certificate types
+        cert_type_len = buf[offset++];
+        PARANOIA_CHECK(pkt_size, offset + cert_type_len);
+        offset += cert_type_len;
+        
+        // supported signature algorithms
+        sig_alg_len = buf[offset++] << 8;
+        sig_alg_len += buf[offset++];
+        PARANOIA_CHECK(pkt_size, offset + sig_alg_len);
+        
+        while (sig_alg_len > 0)
+        {
+            uint8_t hash_alg = buf[offset++];
+            uint8_t sig_alg = buf[offset++];
+            sig_alg_len -= 2;
+
+            if (sig_alg == SIG_ALG_RSA && 
+                    (hash_alg == SIG_ALG_SHA1 ||
+                     hash_alg == SIG_ALG_SHA256 ||
+                     hash_alg == SIG_ALG_SHA384 ||
+                     hash_alg == SIG_ALG_SHA512))
+            {
+                ssl->sig_algs[ssl->num_sig_algs++] = hash_alg;
+            }
+        }
+    }
 error:
 error:
     return ret;
     return ret;
 }
 }
@@ -360,22 +469,40 @@ error:
 static int send_cert_verify(SSL *ssl)
 static int send_cert_verify(SSL *ssl)
 {
 {
     uint8_t *buf = ssl->bm_data;
     uint8_t *buf = ssl->bm_data;
-    uint8_t dgst[MD5_SIZE+SHA1_SIZE];
+    uint8_t dgst[SHA1_SIZE+MD5_SIZE+15];
     RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
     RSA_CTX *rsa_ctx = ssl->ssl_ctx->rsa_ctx;
     int n = 0, ret;
     int n = 0, ret;
+    int offset = 0;
+    int dgst_len;
+
+    if (rsa_ctx == NULL)
+        return SSL_OK;
 
 
     DISPLAY_RSA(ssl, rsa_ctx);
     DISPLAY_RSA(ssl, rsa_ctx);
 
 
     buf[0] = HS_CERT_VERIFY;
     buf[0] = HS_CERT_VERIFY;
     buf[1] = 0;
     buf[1] = 0;
 
 
-    finished_digest(ssl, NULL, dgst);   /* calculate the digest */
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
+    {
+        buf[4] = SIG_ALG_SHA256;
+        buf[5] = SIG_ALG_RSA;
+        offset = 6;
+        memcpy(dgst, g_asn1_sha256, sizeof(g_asn1_sha256));
+        dgst_len = finished_digest(ssl, NULL, &dgst[sizeof(g_asn1_sha256)]) + 
+                        sizeof(g_asn1_sha256);
+    }
+    else
+    {
+        offset = 4;
+        dgst_len = finished_digest(ssl, NULL, dgst);
+    }
 
 
     /* rsa_ctx->bi_ctx is not thread-safe */
     /* rsa_ctx->bi_ctx is not thread-safe */
     if (rsa_ctx)
     if (rsa_ctx)
     {
     {
         SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
         SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
-        n = RSA_encrypt(rsa_ctx, dgst, sizeof(dgst), &buf[6], 1);
+        n = RSA_encrypt(rsa_ctx, dgst, dgst_len, &buf[offset + 2], 1);
         SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
         SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
 
 
         if (n == 0)
         if (n == 0)
@@ -385,9 +512,15 @@ static int send_cert_verify(SSL *ssl)
         }
         }
     }
     }
 
 
-    buf[4] = n >> 8;        /* add the RSA size (not officially documented) */
-    buf[5] = n & 0xff;
+    
+    buf[offset] = n >> 8;        /* add the RSA size */
+    buf[offset+1] = n & 0xff;
     n += 2;
     n += 2;
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
+    {
+        n += 2; // sig/alg
+        offset -= 2;
+    }
     buf[2] = n >> 8;
     buf[2] = n >> 8;
     buf[3] = n & 0xff;
     buf[3] = n & 0xff;
     ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4);
     ret = send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, n+4);

+ 130 - 82
myaxtls/tls1_svr.c

@@ -1,6 +1,6 @@
 /*
 /*
- * Copyright (c) 2007, Cameron Rich
- *
+ * Copyright (c) 2007-2017, Cameron Rich
+ * 
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,11 @@
 #include "ssl.h"
 #include "ssl.h"
 
 
 static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
 static const uint8_t g_hello_done[] = { HS_SERVER_HELLO_DONE, 0, 0, 0 };
+static const uint8_t g_asn1_sha256[] = 
+{ 
+    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 
+    0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+};
 
 
 static int process_client_hello(SSL *ssl);
 static int process_client_hello(SSL *ssl);
 static int send_server_hello_sequence(SSL *ssl);
 static int send_server_hello_sequence(SSL *ssl);
@@ -87,8 +92,10 @@ int do_svr_handshake(SSL *ssl, int handshake_type, uint8_t *buf, int hs_len)
             if (ret == SSL_OK)    /* verify the cert */
             if (ret == SSL_OK)    /* verify the cert */
             {
             {
                 int cert_res;
                 int cert_res;
-                cert_res = x509_verify(
-                        ssl->ssl_ctx->ca_cert_ctx, ssl->x509_ctx);
+                int pathLenConstraint = 0;
+
+                cert_res = x509_verify(ssl->ssl_ctx->ca_cert_ctx, 
+                        ssl->x509_ctx, &pathLenConstraint);
                 ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res);
                 ret = (cert_res == 0) ? SSL_OK : SSL_X509_ERROR(cert_res);
             }
             }
             break;
             break;
@@ -152,102 +159,92 @@ static int process_client_hello(SSL *ssl)
 
 
     offset += id_len;
     offset += id_len;
     cs_len = (buf[offset]<<8) + buf[offset+1];
     cs_len = (buf[offset]<<8) + buf[offset+1];
-    offset += 3;        /* add 1 due to all cipher suites being 8 bit */
+    offset += 2;
 
 
-    PARANOIA_CHECK(pkt_size, offset);
+    PARANOIA_CHECK(pkt_size, offset + cs_len);
 
 
     /* work out what cipher suite we are going to use - client defines
     /* work out what cipher suite we are going to use - client defines
        the preference */
        the preference */
     for (i = 0; i < cs_len; i += 2)
     for (i = 0; i < cs_len; i += 2)
     {
     {
+        /* only support ciphersuites with the form (0x00, xxxx) */
+        if (buf[offset+i])
+            continue;
         for (j = 0; j < NUM_PROTOCOLS; j++)
         for (j = 0; j < NUM_PROTOCOLS; j++)
         {
         {
-            if (ssl_prot_prefs[j] == buf[offset+i])   /* got a match? */
+            if (ssl_prot_prefs[j] == buf[offset+i+1])   /* got a match? */
             {
             {
                 ssl->cipher = ssl_prot_prefs[j];
                 ssl->cipher = ssl_prot_prefs[j];
-                goto do_state;
+                goto do_compression;
             }
             }
         }
         }
     }
     }
 
 
     /* ouch! protocol is not supported */
     /* ouch! protocol is not supported */
-    ret = SSL_ERROR_NO_CIPHER;
-
-do_state:
-error:
-    return ret;
-}
-
-#ifdef CONFIG_SSL_ENABLE_V23_HANDSHAKE
-/*
- * Some browsers use a hybrid SSLv2 "client hello"
- */
-int process_sslv23_client_hello(SSL *ssl)
-{
-    uint8_t *buf = ssl->bm_data;
-    int bytes_needed = ((buf[0] & 0x7f) << 8) + buf[1];
-    int ret = SSL_OK;
+    return SSL_ERROR_NO_CIPHER;
 
 
-    /* we have already read 3 extra bytes so far */
-    int read_len = SOCKET_READ(ssl->client_fd, buf, bytes_needed-3);
-    int cs_len = buf[1];
-    int id_len = buf[3];
-    int ch_len = buf[5];
-    int i, j, offset = 8;   /* start at first cipher */
-    int random_offset = 0;
+    /* completely ignore compression */
+do_compression:
+    offset += cs_len;
+    id_len = buf[offset++];
+    offset += id_len;
+    PARANOIA_CHECK(pkt_size, offset + id_len);
 
 
-    DISPLAY_BYTES(ssl, "received %d bytes", buf, read_len, read_len);
-    
-    /* connection has gone, so die */
-    if (read_len < 0)
+    if (offset == pkt_size)
     {
     {
-        return SSL_ERROR_CONN_LOST;
+        /* no extensions */
+        goto error;
     }
     }
 
 
-    add_packet(ssl, buf, read_len);
-
-    /* now work out what cipher suite we are going to use */
-    for (j = 0; j < NUM_PROTOCOLS; j++)
+    /* extension size */
+    id_len = buf[offset++] << 8;
+    id_len += buf[offset++];
+    PARANOIA_CHECK(pkt_size, offset + id_len);
+    
+    // Check for extensions from the client - only the signature algorithm
+    // is supported
+    while (offset < pkt_size) 
     {
     {
-        for (i = 0; i < cs_len; i += 3)
+        int ext = buf[offset++] << 8;
+        ext += buf[offset++];
+        int ext_len = buf[offset++] << 8;
+        ext_len += buf[offset++];
+        PARANOIA_CHECK(pkt_size, offset + ext_len);
+        
+        if (ext == SSL_EXT_SIG_ALG)
         {
         {
-            if (ssl_prot_prefs[j] == buf[offset+i])
+            while (ext_len > 0)
             {
             {
-                ssl->cipher = ssl_prot_prefs[j];
-                goto server_hello;
+                uint8_t hash_alg = buf[offset++];
+                uint8_t sig_alg = buf[offset++];
+                ext_len -= 2;
+
+                if (sig_alg == SIG_ALG_RSA && 
+                        (hash_alg == SIG_ALG_SHA1 ||
+                         hash_alg == SIG_ALG_SHA256 ||
+                         hash_alg == SIG_ALG_SHA384 ||
+                         hash_alg == SIG_ALG_SHA512))
+                {
+                    ssl->sig_algs[ssl->num_sig_algs++] = hash_alg;
+                }
             }
             }
         }
         }
+        else
+        {
+            offset += ext_len;
+        }
     }
     }
 
 
-    /* ouch! protocol is not supported */
-    ret = SSL_ERROR_NO_CIPHER;
-    goto error;
-
-server_hello:
-    /* get the session id */
-    offset += cs_len - 2;   /* we've gone 2 bytes past the end */
-#ifndef CONFIG_SSL_SKELETON_MODE
-    ssl->session = ssl_session_update(ssl->ssl_ctx->num_sessions,
-            ssl->ssl_ctx->ssl_sessions, ssl, id_len ? &buf[offset] : NULL);
-#endif
-
-    /* get the client random data */
-    offset += id_len;
-
-    /* random can be anywhere between 16 and 32 bytes long - so it is padded
-     * with 0's to the left */
-    if (ch_len == 0x10)
+    /* default is RSA/SHA1 */
+    if (ssl->num_sig_algs == 0)
     {
     {
-        random_offset += 0x10;
+        ssl->sig_algs[ssl->num_sig_algs++] = SIG_ALG_SHA1;
     }
     }
 
 
-    memcpy(&ssl->dc->client_random[random_offset], &buf[offset], ch_len);
-    ret = send_server_hello_sequence(ssl);
 
 
 error:
 error:
     return ret;
     return ret;
 }
 }
-#endif
 
 
 /*
 /*
  * Send the entire server hello sequence
  * Send the entire server hello sequence
@@ -350,7 +347,7 @@ static int send_server_hello(SSL *ssl)
 
 
     buf[offset++] = 0;      /* cipher we are using */
     buf[offset++] = 0;      /* cipher we are using */
     buf[offset++] = ssl->cipher;
     buf[offset++] = ssl->cipher;
-    buf[offset++] = 0;      /* no compression */
+    buf[offset++] = 0;      /* no compression and no extensions supported */
     buf[3] = offset - 4;    /* handshake size */
     buf[3] = offset - 4;    /* handshake size */
     return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
     return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, NULL, offset);
 }
 }
@@ -409,9 +406,6 @@ static int process_client_key_xchg(SSL *ssl)
         /* and continue - will die eventually when checking the mac */
         /* and continue - will die eventually when checking the mac */
     }
     }
 
 
-#if 0
-    print_blob("pre-master", premaster_secret, SSL_SECRET_SIZE);
-#endif
 
 
     generate_master_secret(ssl, premaster_secret);
     generate_master_secret(ssl, premaster_secret);
 
 
@@ -428,15 +422,34 @@ error:
 }
 }
 
 
 #ifdef CONFIG_SSL_CERT_VERIFICATION
 #ifdef CONFIG_SSL_CERT_VERIFICATION
-static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
+static const uint8_t g_cert_request[] = { HS_CERT_REQ, 0, 
+                0, 0x0e, 
+                1, 1, // rsa sign 
+                0x00, 0x08,
+                SIG_ALG_SHA256, SIG_ALG_RSA,
+                SIG_ALG_SHA512, SIG_ALG_RSA,
+                SIG_ALG_SHA384, SIG_ALG_RSA,
+                SIG_ALG_SHA1, SIG_ALG_RSA,
+                0, 0
+};
+
+static const uint8_t g_cert_request_v1[] = { HS_CERT_REQ, 0, 0, 4, 1, 0, 0, 0 };
 
 
 /*
 /*
  * Send the certificate request message.
  * Send the certificate request message.
  */
  */
 static int send_certificate_request(SSL *ssl)
 static int send_certificate_request(SSL *ssl)
 {
 {
-    return send_packet(ssl, PT_HANDSHAKE_PROTOCOL,
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
+    {
+        return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 
             g_cert_request, sizeof(g_cert_request));
             g_cert_request, sizeof(g_cert_request));
+    }
+    else
+    {
+        return send_packet(ssl, PT_HANDSHAKE_PROTOCOL, 
+            g_cert_request_v1, sizeof(g_cert_request_v1));
+    }
 }
 }
 
 
 /*
 /*
@@ -448,29 +461,64 @@ static int process_cert_verify(SSL *ssl)
     uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
     uint8_t *buf = &ssl->bm_data[ssl->dc->bm_proc_index];
     int pkt_size = ssl->bm_index;
     int pkt_size = ssl->bm_index;
     uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
     uint8_t dgst_buf[MAX_KEY_BYTE_SIZE];
-    uint8_t dgst[MD5_SIZE+SHA1_SIZE];
+    uint8_t dgst[MD5_SIZE + SHA1_SIZE];
     X509_CTX *x509_ctx = ssl->x509_ctx;
     X509_CTX *x509_ctx = ssl->x509_ctx;
     int ret = SSL_OK;
     int ret = SSL_OK;
+    int offset = 6;
+    int rsa_len;
     int n;
     int n;
 
 
-    PARANOIA_CHECK(pkt_size, x509_ctx->rsa_ctx->num_octets+6);
     DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
     DISPLAY_RSA(ssl, x509_ctx->rsa_ctx);
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
+    {
+        // TODO: should really need to be able to handle other algorihms. An 
+        // assumption is made on RSA/SHA256 and appears to be OK.
+        //uint8_t hash_alg = buf[4];
+        //uint8_t sig_alg = buf[5];
+        offset = 8;
+        rsa_len = (buf[6] << 8) + buf[7];
+    }
+    else
+    {
+        rsa_len = (buf[4] << 8) + buf[5];
+    }
+
+    PARANOIA_CHECK(pkt_size, offset + rsa_len);
 
 
     /* rsa_ctx->bi_ctx is not thread-safe */
     /* rsa_ctx->bi_ctx is not thread-safe */
     SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
     SSL_CTX_LOCK(ssl->ssl_ctx->mutex);
-    n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[6], dgst_buf, sizeof(dgst_buf), 0);
+    n = RSA_decrypt(x509_ctx->rsa_ctx, &buf[offset], dgst_buf, 
+                    sizeof(dgst_buf), 0);
     SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
     SSL_CTX_UNLOCK(ssl->ssl_ctx->mutex);
 
 
-    if (n != SHA1_SIZE + MD5_SIZE)
+    if (ssl->version >= SSL_PROTOCOL_VERSION_TLS1_2) // TLS1.2+
     {
     {
-        ret = SSL_ERROR_INVALID_KEY;
-        goto end_cert_vfy;
-    }
+        if (memcmp(dgst_buf, g_asn1_sha256, sizeof(g_asn1_sha256)))
+        {
+            ret = SSL_ERROR_INVALID_KEY;
+            goto error;
+        }
 
 
-    finished_digest(ssl, NULL, dgst);       /* calculate the digest */
-    if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE))
+        finished_digest(ssl, NULL, dgst);       /* calculate the digest */
+        if (memcmp(&dgst_buf[sizeof(g_asn1_sha256)], dgst, SHA256_SIZE))
+        {
+            ret = SSL_ERROR_INVALID_KEY;
+            goto error;
+        }
+    }
+    else // TLS1.0/1.1
     {
     {
-        ret = SSL_ERROR_INVALID_KEY;
+        if (n != SHA1_SIZE + MD5_SIZE)
+        {
+            ret = SSL_ERROR_INVALID_KEY;
+            goto end_cert_vfy;
+        }
+
+        finished_digest(ssl, NULL, dgst);       /* calculate the digest */
+        if (memcmp(dgst_buf, dgst, MD5_SIZE + SHA1_SIZE))
+        {
+            ret = SSL_ERROR_INVALID_KEY;
+        }
     }
     }
 
 
 end_cert_vfy:
 end_cert_vfy:

+ 1 - 1
myaxtls/version.h

@@ -1 +1 @@
-#define AXTLS_VERSION    "1.5.1"
+#define AXTLS_VERSION    "2.1.4"

+ 342 - 64
myaxtls/x509.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2007-2015, Cameron Rich
+ * Copyright (c) 2007-2017, Cameron Rich
  * 
  * 
  * All rights reserved.
  * All rights reserved.
  * 
  * 
@@ -42,6 +42,12 @@
 #include "crypto_misc.h"
 #include "crypto_misc.h"
 
 
 #ifdef CONFIG_SSL_CERT_VERIFICATION
 #ifdef CONFIG_SSL_CERT_VERIFICATION
+static int x509_v3_subject_alt_name(const uint8_t *cert, int offset, 
+        X509_CTX *x509_ctx);
+static int x509_v3_basic_constraints(const uint8_t *cert, int offset, 
+        X509_CTX *x509_ctx);
+static int x509_v3_key_usage(const uint8_t *cert, int offset, 
+        X509_CTX *x509_ctx);
 /**
 /**
  * Retrieve the signature from a certificate.
  * Retrieve the signature from a certificate.
  */
  */
@@ -73,8 +79,11 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
 {
 {
     int begin_tbs, end_tbs;
     int begin_tbs, end_tbs;
     int ret = X509_NOT_OK, offset = 0, cert_size = 0;
     int ret = X509_NOT_OK, offset = 0, cert_size = 0;
+    int version = 0;
     X509_CTX *x509_ctx;
     X509_CTX *x509_ctx;
+#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
     BI_CTX *bi_ctx;
     BI_CTX *bi_ctx;
+#endif
 
 
     *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
     *ctx = (X509_CTX *)calloc(1, sizeof(X509_CTX));
     x509_ctx = *ctx;
     x509_ctx = *ctx;
@@ -92,11 +101,10 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
     if (asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
         goto end_cert;
         goto end_cert;
 
 
-    if (cert[offset] == ASN1_EXPLICIT_TAG)   /* optional version */
-    {
-        if (asn1_version(cert, &offset, x509_ctx))
-            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 */ 
     if (asn1_skip_obj(cert, &offset, ASN1_INTEGER) || /* serial number */ 
             asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
             asn1_next_obj(cert, &offset, ASN1_SEQUENCE) < 0)
@@ -117,9 +125,9 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
         goto end_cert;
         goto end_cert;
     }
     }
 
 
+#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
     bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
     bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
 
 
-#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
     /* use the appropriate signature algorithm */
     /* use the appropriate signature algorithm */
     switch (x509_ctx->sig_type)
     switch (x509_ctx->sig_type)
     {
     {
@@ -181,50 +189,11 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
 #endif
 #endif
     }
     }
 
 
-    if (cert[offset] == ASN1_V3_DATA)
+    if (version == 2 && asn1_next_obj(cert, &offset, ASN1_V3_DATA) > 0)
     {
     {
-        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;
-                    }
-                }
-            }
-        }
+        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 */
     offset = end_tbs;   /* skip the rest of v3 data */
@@ -251,6 +220,126 @@ end_cert:
 
 
     return ret;
     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;
+}
+
+/**
+ * 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, l= 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;
+}
+
+/*
+ * 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;
+}
+#endif
 
 
 /**
 /**
  * Free an X.509 object's resources.
  * Free an X.509 object's resources.
@@ -345,8 +434,10 @@ static bigint *sig_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,
  * - That the certificate(s) are not self-signed.
  * - That the certificate(s) are not self-signed.
  * - The certificate chain is valid.
  * - The certificate chain is valid.
  * - The signature of the certificate is valid.
  * - The signature of the certificate is valid.
+ * - Basic constraints 
  */
  */
-int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert) 
+int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert, 
+        int *pathLenConstraint) 
 {
 {
     int ret = X509_OK, i = 0;
     int ret = X509_OK, i = 0;
     bigint *cert_sig;
     bigint *cert_sig;
@@ -389,6 +480,33 @@ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
         goto end_verify;
         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;
     next_cert = cert->next;
 
 
     /* last cert in the chain - look for a trusted cert */
     /* last cert in the chain - look for a trusted cert */
@@ -396,14 +514,21 @@ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
     {
     {
        if (ca_cert_ctx != NULL) 
        if (ca_cert_ctx != NULL) 
        {
        {
-            /* go thu the CA store */
+            /* go through the CA store */
             while (i < CONFIG_X509_MAX_CA_CERTS && ca_cert_ctx->cert[i])
             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,
                 if (asn1_compare_dn(cert->ca_cert_dn,
                                             ca_cert_ctx->cert[i]->cert_dn) == 0)
                                             ca_cert_ctx->cert[i]->cert_dn) == 0)
                 {
                 {
                     /* use this CA certificate for signature verification */
                     /* use this CA certificate for signature verification */
-                    match_ca_cert = 1;
+                    match_ca_cert = true;
                     ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
                     ctx = ca_cert_ctx->cert[i]->rsa_ctx->bi_ctx;
                     mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
                     mod = ca_cert_ctx->cert[i]->rsa_ctx->m;
                     expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
                     expn = ca_cert_ctx->cert[i]->rsa_ctx->e;
@@ -465,7 +590,8 @@ int x509_verify(const CA_CERT_CTX *ca_cert_ctx, const X509_CTX *cert)
     /* go down the certificate chain using recursion. */
     /* go down the certificate chain using recursion. */
     if (next_cert != NULL)
     if (next_cert != NULL)
     {
     {
-        ret = x509_verify(ca_cert_ctx, next_cert);
+        (*pathLenConstraint)++; /* don't include last certificate */
+        ret = x509_verify(ca_cert_ctx, next_cert, pathLenConstraint);
     }
     }
 
 
 end_verify:
 end_verify:
@@ -492,9 +618,140 @@ void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
     printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
     printf("%s\n", cert->cert_dn[X509_ORGANIZATION] ?
         cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
         cert->cert_dn[X509_ORGANIZATION] : not_part_of_cert);
 
 
-    printf("Organizational Unit (OU):\t");
-    printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT] ?
-        cert->cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
+    if (cert->cert_dn[X509_ORGANIZATIONAL_UNIT]) 
+    {
+        printf("Organizational Unit (OU):\t");
+        printf("%s\n", cert->cert_dn[X509_ORGANIZATIONAL_UNIT]);
+    }
+
+    if (cert->cert_dn[X509_LOCATION]) 
+    {
+        printf("Location (L):\t\t\t");
+        printf("%s\n", cert->cert_dn[X509_LOCATION]);
+    }
+
+    if (cert->cert_dn[X509_COUNTRY]) 
+    {
+        printf("Country (C):\t\t\t");
+        printf("%s\n", cert->cert_dn[X509_COUNTRY]);
+    }
+
+    if (cert->cert_dn[X509_STATE]) 
+    {
+        printf("State (ST):\t\t\t");
+        printf("%s\n", cert->cert_dn[X509_STATE]);
+    }
+
+    if (cert->basic_constraint_present)
+    {
+        printf("Basic Constraints:\t\t%sCA:%s, pathlen:%d\n",
+                cert->basic_constraint_is_critical ? 
+                    "critical, " : "",
+                cert->basic_constraint_cA? "TRUE" : "FALSE",
+                cert->basic_constraint_pathLenConstraint);
+    }
+
+    if (cert->key_usage_present)
+    {
+        printf("Key Usage:\t\t\t%s", cert->key_usage_is_critical ? 
+                    "critical, " : "");
+        bool has_started = false;
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_DIGITAL_SIGNATURE))
+        {
+            printf("Digital Signature");
+            has_started = true;
+        }
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_NON_REPUDIATION))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Non Repudiation");
+            has_started = true;
+        }
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_ENCIPHERMENT))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Key Encipherment");
+            has_started = true;
+        }
+        
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_DATA_ENCIPHERMENT))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Data Encipherment");
+            has_started = true;
+        }
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_AGREEMENT))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Key Agreement");
+            has_started = true;
+        }
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_KEY_CERT_SIGN))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Key Cert Sign");
+            has_started = true;
+        }
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_CRL_SIGN))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("CRL Sign");
+            has_started = true;
+        }
+       
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_ENCIPHER_ONLY))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Encipher Only");
+            has_started = true;
+        }
+
+        if (IS_SET_KEY_USAGE_FLAG(cert, KEY_USAGE_DECIPHER_ONLY))
+        {
+            if (has_started)
+                printf(", ");
+
+            printf("Decipher Only");
+            has_started = true;
+        }
+
+        printf("\n");
+    }
+
+    if (cert->subject_alt_name_present)
+    {
+        printf("Subject Alt Name:\t\t%s", cert->subject_alt_name_is_critical 
+                ?  "critical, " : "");
+        if (cert->subject_alt_dnsnames)
+        {
+            int i = 0;
+
+            while (cert->subject_alt_dnsnames[i])
+                printf("%s ", cert->subject_alt_dnsnames[i++]);
+        }
+        printf("\n");
+
+    }
 
 
     printf("=== CERTIFICATE ISSUED BY ===\n");
     printf("=== CERTIFICATE ISSUED BY ===\n");
     printf("Common Name (CN):\t\t");
     printf("Common Name (CN):\t\t");
@@ -505,9 +762,29 @@ void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
     printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
     printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATION] ?
         cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
         cert->ca_cert_dn[X509_ORGANIZATION] : not_part_of_cert);
 
 
-    printf("Organizational Unit (OU):\t");
-    printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] ?
-        cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT] : not_part_of_cert);
+    if (cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT]) 
+    {
+        printf("Organizational Unit (OU):\t");
+        printf("%s\n", cert->ca_cert_dn[X509_ORGANIZATIONAL_UNIT]);
+    }
+
+    if (cert->ca_cert_dn[X509_LOCATION]) 
+    {
+        printf("Location (L):\t\t\t");
+        printf("%s\n", cert->ca_cert_dn[X509_LOCATION]);
+    }
+
+    if (cert->ca_cert_dn[X509_COUNTRY]) 
+    {
+        printf("Country (C):\t\t\t");
+        printf("%s\n", cert->ca_cert_dn[X509_COUNTRY]);
+    }
+
+    if (cert->ca_cert_dn[X509_STATE]) 
+    {
+        printf("State (ST):\t\t\t");
+        printf("%s\n", cert->ca_cert_dn[X509_STATE]);
+    }
 
 
     printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
     printf("Not Before:\t\t\t%s", ctime(&cert->not_before));
     printf("Not After:\t\t\t%s", ctime(&cert->not_after));
     printf("Not After:\t\t\t%s", ctime(&cert->not_after));
@@ -515,9 +792,6 @@ void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
     printf("Sig Type:\t\t\t");
     printf("Sig Type:\t\t\t");
     switch (cert->sig_type)
     switch (cert->sig_type)
     {
     {
-        case SIG_TYPE_MD2:
-            printf("MD2\n");
-            break;
         case SIG_TYPE_MD5:
         case SIG_TYPE_MD5:
             printf("MD5\n");
             printf("MD5\n");
             break;
             break;
@@ -540,8 +814,10 @@ void x509_print(const X509_CTX *cert, CA_CERT_CTX *ca_cert_ctx)
 
 
     if (ca_cert_ctx)
     if (ca_cert_ctx)
     {
     {
+        int pathLenConstraint = 0;
         printf("Verify:\t\t\t\t%s\n",
         printf("Verify:\t\t\t\t%s\n",
-                x509_display_error(x509_verify(ca_cert_ctx, cert)));
+                x509_display_error(x509_verify(ca_cert_ctx, cert,
+                        &pathLenConstraint)));
     }
     }
 
 
 #if 0
 #if 0
@@ -591,6 +867,8 @@ const char * x509_display_error(int error)
 
 
         case X509_INVALID_PRIV_KEY:
         case X509_INVALID_PRIV_KEY:
             return "Invalid private key";
             return "Invalid private key";
+        case X509_VFY_ERROR_BASIC_CONSTRAINT:
+            return "Basic constraint invalid";
 
 
         default:
         default:
             return "Unknown";
             return "Unknown";

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio