diff --git a/src/include.am b/src/include.am index 508ff051d..d2c40e6de 100644 --- a/src/include.am +++ b/src/include.am @@ -19,6 +19,7 @@ MAINTAINERCLEANFILES+= $(FIPS_FILES) EXTRA_DIST += src/bio.c EXTRA_DIST += src/conf.c EXTRA_DIST += src/pk.c +EXTRA_DIST += src/ssl_asn1.c EXTRA_DIST += src/ssl_bn.c EXTRA_DIST += src/ssl_misc.c EXTRA_DIST += src/x509.c diff --git a/src/ssl.c b/src/ssl.c index 57a3b48d2..cbd79414e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -150,6 +150,9 @@ int wolfssl_bn_get_value(WOLFSSL_BIGNUM* bn, mp_int* mpi); int wolfssl_bn_set_value(WOLFSSL_BIGNUM** bn, mp_int* mpi); #endif +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + static int wolfssl_bn_set_neg(WOLFSSL_BIGNUM* bn, int n); +#endif #if defined(WOLFSSL_QT) #include @@ -208,6 +211,11 @@ #define WOLFSSL_EVP_INCLUDED #include "wolfcrypt/src/evp.c" +#ifndef OPENSSL_EXTRA_NO_ASN1 +#define WOLFSSL_SSL_ASN1_INCLUDED +#include "src/ssl_asn1.c" +#endif /* OPENSSL_EXTRA_NO_ASN1 */ + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ !defined(WOLFCRYPT_ONLY) /* Convert shortname to NID. @@ -392,11 +400,6 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) } #endif -#ifndef OPENSSL_EXTRA_NO_PK -#define WOLFSSL_PK_INCLUDED -#include "src/pk.c" -#endif - #ifdef OPENSSL_EXTRA /* Global pointer to constant BN on */ static WOLFSSL_BIGNUM* bn_one = NULL; @@ -410,6 +413,12 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) #endif /* !WOLFSSL_NO_OPENSSL_RAND_CB */ #endif /* OPENSSL_EXTRA */ +#define WOLFSSL_SSL_BN_INCLUDED +#include "src/ssl_bn.c" + +#define WOLFSSL_PK_INCLUDED +#include "src/pk.c" + #include #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) @@ -10794,77 +10803,7 @@ int wolfSSL_check_private_key(const WOLFSSL* ssl) } #endif /* !NO_CHECK_PRIVATE_KEY */ -#if defined(OPENSSL_ALL) - -int wolfSSL_ASN1_BIT_STRING_set_bit(WOLFSSL_ASN1_BIT_STRING* str, int pos, - int val) -{ - int bytes_cnt, bit; - byte* temp; - - if (!str || (val != 0 && val != 1) || pos < 0) { - return WOLFSSL_FAILURE; - } - - bytes_cnt = pos/8; - bit = 1<<(7-(pos%8)); - - if (bytes_cnt+1 > str->length) { - if (!(temp = (byte*)XREALLOC(str->data, bytes_cnt+1, NULL, - DYNAMIC_TYPE_OPENSSL))) { - return WOLFSSL_FAILURE; - } - XMEMSET(temp+str->length, 0, bytes_cnt+1 - str->length); - str->data = temp; - str->length = bytes_cnt+1; - } - - str->data[bytes_cnt] &= ~bit; - str->data[bytes_cnt] |= val ? bit : 0; - - return WOLFSSL_SUCCESS; -} - -#endif /* OPENSSL_ALL */ - #endif /* !NO_CERTS */ -#endif /* OPENSSL_EXTRA */ - -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void) -{ - WOLFSSL_ASN1_BIT_STRING* str; - - str = (WOLFSSL_ASN1_BIT_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_BIT_STRING), - NULL, DYNAMIC_TYPE_OPENSSL); - if (str) { - XMEMSET(str, 0, sizeof(WOLFSSL_ASN1_BIT_STRING)); - } - return str; -} - -void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING* str) -{ - if (str) { - if (str->data) { - XFREE(str->data, NULL, DYNAMIC_TYPE_OPENSSL); - str->data = NULL; - } - XFREE(str, NULL, DYNAMIC_TYPE_OPENSSL); - } -} - -int wolfSSL_ASN1_BIT_STRING_get_bit(const WOLFSSL_ASN1_BIT_STRING* str, int i) -{ - if (!str || !str->data || str->length <= (i/8) || i < 0) { - return WOLFSSL_FAILURE; - } - - return (str->data[i/8] & (1<<(7-(i%8)))) ? 1 : 0; -} -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -#ifdef OPENSSL_EXTRA int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) { @@ -20929,311 +20868,6 @@ WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx) #endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ #endif /* NO_CERTS */ - -#if !defined(NO_ASN) && (defined(OPENSSL_EXTRA) || \ - defined(OPENSSL_EXTRA_X509_SMALL)) -void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) -{ - if (obj == NULL) { - return; - } - if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) { -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("Freeing ASN1 data"); -#endif - XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1); - obj->obj = NULL; - } - #if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - if (obj->pathlen != NULL) { - wolfSSL_ASN1_INTEGER_free(obj->pathlen); - obj->pathlen = NULL; - } - #endif - if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) { -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_MSG("Freeing ASN1 OBJECT"); -#endif - XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); - } -} - -WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) -{ - WOLFSSL_ASN1_OBJECT* obj; - - obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL, - DYNAMIC_TYPE_ASN1); - if (obj == NULL) { - return NULL; - } - - XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT)); - obj->d.ia5 = &(obj->d.ia5_internal); -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) - obj->d.iPAddress = &(obj->d.iPAddress_internal); -#endif - obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; - return obj; -} - -WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_dup(WOLFSSL_ASN1_OBJECT* obj) -{ - WOLFSSL_ASN1_OBJECT* dupl = NULL; - - WOLFSSL_ENTER("wolfSSL_ASN1_OBJECT_dup"); - - if (!obj) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - dupl = wolfSSL_ASN1_OBJECT_new(); - if (!dupl) { - WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new error"); - return NULL; - } - /* Copy data */ - XMEMCPY(dupl->sName, obj->sName, WOLFSSL_MAX_SNAME); - dupl->type = obj->type; - dupl->grp = obj->grp; - dupl->nid = obj->nid; - dupl->objSz = obj->objSz; - if (obj->obj) { - dupl->obj = (const unsigned char*)XMALLOC( - obj->objSz, NULL, DYNAMIC_TYPE_ASN1); - if (!dupl->obj) { - WOLFSSL_MSG("ASN1 obj malloc error"); - wolfSSL_ASN1_OBJECT_free(dupl); - return NULL; - } - XMEMCPY((byte*)dupl->obj, obj->obj, obj->objSz); - dupl->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; - } - return dupl; -} -#endif /* !NO_ASN && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ - -#ifndef NO_ASN -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -/* Creates and returns a new WOLFSSL_CIPHER stack. */ -WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void) -{ - WOLFSSL_STACK* sk; - WOLFSSL_ENTER("wolfSSL_sk_new_asn1_obj"); - - sk = wolfSSL_sk_new_null(); - if (sk == NULL) - return NULL; - sk->type = STACK_TYPE_OBJ; - - return sk; -} - -/* return 1 on success 0 on fail */ -int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, - WOLFSSL_ASN1_OBJECT* obj) -{ - WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push"); - - if (sk == NULL || obj == NULL) { - return WOLFSSL_FAILURE; - } - - return wolfSSL_sk_push(sk, obj); -} - - -WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( - WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) -{ - WOLFSSL_STACK* node; - WOLFSSL_ASN1_OBJECT* obj; - - if (sk == NULL) { - return NULL; - } - - node = sk->next; - obj = sk->data.obj; - - if (node != NULL) { /* update sk and remove node from stack */ - sk->data.obj = node->data.obj; - sk->next = node->next; - XFREE(node, NULL, DYNAMIC_TYPE_ASN1); - } - else { /* last obj in stack */ - sk->data.obj = NULL; - } - - if (sk->num > 0) { - sk->num -= 1; - } - - return obj; -} - - -/* Free the structure for ASN1_OBJECT stack - * - * sk stack to free nodes in - */ -void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) -{ - wolfSSL_sk_free(sk); -} - -/* Free's all nodes in ASN1_OBJECT stack. - * This is different then wolfSSL_ASN1_OBJECT_free in that it allows for - * choosing the function to use when freeing an ASN1_OBJECT stack. - * - * sk stack to free nodes in - * f X509 free function - */ -void wolfSSL_sk_ASN1_OBJECT_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, - void (*f) (WOLFSSL_ASN1_OBJECT*)) -{ - WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_pop_free"); - wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); -} - -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ -#endif /* !NO_ASN */ - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) -#ifndef NO_ASN - -int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in) -{ - /* - ASN1_STRING_to_UTF8() converts the string in to UTF8 format, - the converted data is allocated in a buffer in *out. - The length of out is returned or a negative error code. - The buffer *out should be free using OPENSSL_free(). - */ - unsigned char* buf; - unsigned char* inPtr; - int inLen; - - if (!out || !in) { - return -1; - } - - inPtr = wolfSSL_ASN1_STRING_data(in); - inLen = wolfSSL_ASN1_STRING_length(in); - if (!inPtr || inLen < 0) { - return -1; - } - buf = (unsigned char*)XMALLOC(inLen + 1, NULL, DYNAMIC_TYPE_OPENSSL); - if (!buf) { - return -1; - } - XMEMCPY(buf, inPtr, inLen + 1); - *out = buf; - return inLen; -} -#endif /* !NO_ASN */ -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - -#if defined(OPENSSL_EXTRA) -#ifndef NO_ASN - -int wolfSSL_ASN1_UNIVERSALSTRING_to_string(WOLFSSL_ASN1_STRING *s) -{ - char *idx; - char *copy; - WOLFSSL_ENTER("wolfSSL_ASN1_UNIVERSALSTRING_to_string"); - - if (!s) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - - if (s->type != V_ASN1_UNIVERSALSTRING) { - WOLFSSL_MSG("Input is not a universal string"); - return WOLFSSL_FAILURE; - } - - if ((s->length % 4) != 0) { - WOLFSSL_MSG("Input string must be divisible by 4"); - return WOLFSSL_FAILURE; - } - - for (idx = s->data; idx < s->data + s->length; idx += 4) - if ((idx[0] != '\0') || (idx[1] != '\0') || (idx[2] != '\0')) - break; - - if (idx != s->data + s->length) { - WOLFSSL_MSG("Wrong string format"); - return WOLFSSL_FAILURE; - } - - for (copy = idx = s->data; idx < s->data + s->length; idx += 4) - *copy++ = idx[3]; - *copy = '\0'; - s->length /= 4; - s->type = V_ASN1_PRINTABLESTRING; - return WOLFSSL_SUCCESS; -} - -/* Returns string representation of ASN1_STRING */ -char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method, - const WOLFSSL_ASN1_STRING *s) -{ - int i; - int tmpSz = 100; - int valSz = 5; - char* tmp; - char val[5]; - unsigned char* str; - - WOLFSSL_ENTER("wolfSSL_i2s_ASN1_STRING"); - (void)method; - - if(s == NULL || s->data == NULL) { - WOLFSSL_MSG("Bad Function Argument"); - return NULL; - } - str = (unsigned char*)XMALLOC(s->length, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (str == NULL) { - WOLFSSL_MSG("Memory Error"); - return NULL; - } - XMEMCPY(str, (unsigned char*)s->data, s->length); - - tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmp == NULL) { - WOLFSSL_MSG("Memory Error"); - XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - XMEMSET(tmp, 0, tmpSz); - - for (i = 0; i < tmpSz && i < (s->length - 1); i++) { - if (XSNPRINTF(val, valSz, "%02X:", str[i]) - >= valSz) - { - WOLFSSL_MSG("Buffer overrun"); - XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - XSTRNCAT(tmp, val, valSz); - } - if (XSNPRINTF(val, valSz, "%02X", str[i]) - >= valSz) - { - WOLFSSL_MSG("Buffer overrun"); - XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return NULL; - } - - XSTRNCAT(tmp, val, valSz); - XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return tmp; -} -#endif /* NO_ASN */ -#endif /* OPENSSL_EXTRA */ - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) void wolfSSL_set_connect_state(WOLFSSL* ssl) { @@ -22200,283 +21834,6 @@ const char* wolfSSL_get_curve_name(WOLFSSL* ssl) } #endif -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ - defined(OPENSSL_EXTRA_X509_SMALL) - - /* Creates a new WOLFSSL_ASN1_STRING structure. - * - * returns a pointer to the new structure created on success or NULL if fail - */ - WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void) - { - WOLFSSL_ASN1_STRING* asn1; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new"); -#endif - - asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL, - DYNAMIC_TYPE_OPENSSL); - if (asn1 != NULL) { - XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING)); - } - - return asn1; /* no check for null because error case is returning null*/ - } - - /** - * Used to duplicate a passed in WOLFSSL_ASN1_STRING* - * @param asn1 WOLFSSL_ASN1_STRING* to be duplicated - * @return WOLFSSL_ASN1_STRING* the duplicate struct or NULL on error - */ - WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_dup(WOLFSSL_ASN1_STRING* asn1) - { - WOLFSSL_ASN1_STRING* dupl = NULL; - - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_dup"); - if (!asn1) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - - dupl = wolfSSL_ASN1_STRING_new(); - if (!dupl) { - WOLFSSL_MSG("wolfSSL_ASN1_STRING_new error"); - return NULL; - } - - dupl->type = asn1->type; - dupl->flags = asn1->flags; - - if (wolfSSL_ASN1_STRING_set(dupl, asn1->data, asn1->length) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error"); - wolfSSL_ASN1_STRING_free(dupl); - return NULL; - } - - return dupl; - } - - - /* used to free a WOLFSSL_ASN1_STRING structure */ - void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1) - { -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free"); -#endif - - if (asn1 != NULL) { - if (asn1->length > 0 && asn1->data != NULL && asn1->isDynamic) { - XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); - } - XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL); - } - } - - int wolfSSL_ASN1_STRING_cmp(const WOLFSSL_ASN1_STRING *a, const WOLFSSL_ASN1_STRING *b) - { - int i; - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_cmp"); - - if (!a || !b) { - return WOLFSSL_FATAL_ERROR; - } - - if (a->length != b->length) { - return a->length - b->length; - } - - if ((i = XMEMCMP(a->data, b->data, a->length)) != 0) { - return i; - } - - return a->type - b->type; - } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -#if !defined(NO_CERTS) && (defined(OPENSSL_EXTRA) || \ - defined(OPENSSL_EXTRA_X509_SMALL)) - - int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dest, - const WOLFSSL_ASN1_STRING* src) - { - if (src == NULL || dest == NULL) { - return WOLFSSL_FAILURE; - } - dest->type = src->type; - if(wolfSSL_ASN1_STRING_set(dest, src->data, src->length) - != WOLFSSL_SUCCESS) { - return WOLFSSL_FAILURE; - } - dest->flags = src->flags; - - return WOLFSSL_SUCCESS; - } - /* Creates a new WOLFSSL_ASN1_STRING structure given the input type. - * - * type is the type of set when WOLFSSL_ASN1_STRING is created - * - * returns a pointer to the new structure created on success or NULL if fail - */ - WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type) - { - WOLFSSL_ASN1_STRING* asn1; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new"); -#endif - - asn1 = wolfSSL_ASN1_STRING_new(); - if (asn1 == NULL) { - return NULL; - } - asn1->type = type; - - return asn1; - } - - -/****************************************************************************** -* wolfSSL_ASN1_STRING_type - returns the type of -* -* RETURNS: -* returns the type set for . Otherwise, returns WOLFSSL_FAILURE. -*/ - int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1) - { - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type"); -#endif - - if (asn1 == NULL) { - return WOLFSSL_FAILURE; - } - - return asn1->type; - } - -#endif /* !NO_CERTS && OPENSSL_EXTRA */ - -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) || \ - defined(OPENSSL_EXTRA_X509_SMALL) - /* if dataSz is negative then use XSTRLEN to find length of data - * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ - /* `data` can be NULL and only buffer will be allocated */ - int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, - int dataSz) - { - int sz; - -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set"); -#endif - - if (asn1 == NULL || (data == NULL && dataSz < 0)) { - return WOLFSSL_FAILURE; - } - - if (dataSz < 0) { - sz = (int)XSTRLEN((const char*)data); - } - else { - sz = dataSz; - } - - if (sz < 0) { - return WOLFSSL_FAILURE; - } - - /* free any existing data before copying */ - if (asn1->data != NULL && asn1->isDynamic) { - XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); - asn1->data = NULL; - } - - if (sz + 1 > CTC_NAME_SIZE) { /* account for null char */ - /* create new data buffer and copy over */ - asn1->data = (char*)XMALLOC(sz + 1, NULL, DYNAMIC_TYPE_OPENSSL); - if (asn1->data == NULL) { - return WOLFSSL_FAILURE; - } - asn1->isDynamic = 1; - } - else { - XMEMSET(asn1->strData, 0, CTC_NAME_SIZE); - asn1->data = asn1->strData; - asn1->isDynamic = 0; - } - if (data != NULL) { - XMEMCPY(asn1->data, data, sz); - asn1->data[sz] = '\0'; - } - asn1->length = sz; - - return WOLFSSL_SUCCESS; - } -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -#ifndef NO_CERTS -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - const unsigned char* wolfSSL_ASN1_STRING_get0_data( - const WOLFSSL_ASN1_STRING* asn) - { - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_get0_data"); - - if (asn) { - return (const unsigned char*)asn->data; - } else { - return NULL; - } - } - unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn) - { -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data"); -#endif - - if (asn) { - return (unsigned char*)asn->data; - } - else { - return NULL; - } - } - - - int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn) - { -#ifdef WOLFSSL_DEBUG_OPENSSL - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length"); -#endif - - if (asn) { - return asn->length; - } - else { - return 0; - } - } -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - -#ifdef OPENSSL_EXTRA -#ifndef NO_WOLFSSL_STUB - WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn, - const unsigned char **in, long len) - { - WOLFSSL_STUB("d2i_DISPLAYTEXT"); - (void)asn; - (void)in; - (void)len; - return NULL; - } -#endif - -#endif /* OPENSSL_EXTRA */ - -#endif /* !NO_CERTS */ - #ifdef OPENSSL_EXTRA #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) /* return authentication NID corresponding to cipher suite @@ -23387,548 +22744,6 @@ WOLFSSL_X509_VERIFY_PARAM* wolfSSL_get0_param(WOLFSSL* ssl) #endif /* OPENSSL_EXTRA */ -#if defined(OPENSSL_EXTRA) -int wolfSSL_i2d_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER* a, unsigned char** out) -{ - int ret = 0; - word32 idx = 0; - int len; - int preAlloc = 1; - - WOLFSSL_ENTER("wolfSSL_i2d_ASN1_INTEGER"); - - if (a == NULL || a->data == NULL || a->length <= 0 || out == NULL) { - WOLFSSL_MSG("Bad parameter."); - ret = WOLFSSL_FATAL_ERROR; - } - - if (ret == 0 && *out == NULL) { - preAlloc = 0; - *out = (unsigned char*)XMALLOC(a->length, NULL, DYNAMIC_TYPE_ASN1); - if (*out == NULL) { - WOLFSSL_MSG("Failed to allocate output buffer."); - ret = WOLFSSL_FATAL_ERROR; - } - } - if (ret == 0) { - /* - * A WOLFSSL_ASN1_INTEGER stores the DER buffer of the integer in its - * "data" field, but it's only the magnitude of the number (i.e. the - * sign isn't encoded). The "negative" field is 1 if the value should - * be interpreted as negative and 0 otherwise. If the value is negative, - * we need to output the 2's complement of the value in the DER output. - */ - XMEMCPY(*out, a->data, a->length); - if (a->negative) { - if (GetLength(a->data, &idx, &len, a->length) < 0) { - ret = WOLFSSL_FATAL_ERROR; - } - else { - ++idx; - for (; (int)idx < a->length; ++idx) { - (*out)[idx] = ~(*out)[idx]; - } - do { - --idx; - ++(*out)[idx]; - } while ((*out)[idx] == 0); - } - } - } - if (ret == 0) { - ret = a->length; - if (preAlloc) { - *out += a->length; - } - } - - WOLFSSL_LEAVE("wolfSSL_i2d_ASN1_INTEGER", ret); - - return ret; -} - -WOLFSSL_ASN1_INTEGER* wolfSSL_d2i_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER** a, - const unsigned char** in, - long inSz) -{ - WOLFSSL_ASN1_INTEGER* ret = NULL; - int err = 0; - word32 idx = 0; - int len; - - WOLFSSL_ENTER("wolfSSL_d2i_ASN1_INTEGER"); - - if (in == NULL || *in == NULL || inSz <= 0) { - WOLFSSL_MSG("Bad parameter"); - err = 1; - } - - if (err == 0 && (*in)[0] != ASN_INTEGER) { - WOLFSSL_MSG("Tag doesn't indicate integer type."); - err = 1; - } - if (err == 0) { - ret = wolfSSL_ASN1_INTEGER_new(); - if (ret == NULL) { - err = 1; - } - else { - ret->type = V_ASN1_INTEGER; - } - } - if (err == 0 && inSz > (long)sizeof(ret->intData)) { - ret->data = (unsigned char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_ASN1); - if (ret->data == NULL) { - err = 1; - } - else { - ret->isDynamic = 1; - ret->dataMax = (word32)inSz; - } - } - if (err == 0) { - XMEMCPY(ret->data, *in, inSz); - ret->length = (word32)inSz; - /* Advance to the end of the length field.*/ - if (GetLength(*in, &idx, &len, (word32)inSz) < 0) { - err = 1; - } - else { - /* See 2's complement comment in wolfSSL_d2i_ASN1_INTEGER. */ - ret->negative = (*in)[idx+1] & 0x80; - if (ret->negative) { - ++idx; - for (; (int)idx < inSz; ++idx) { - ret->data[idx] = ~ret->data[idx]; - } - do { - --idx; - ++ret->data[idx]; - } while (ret->data[idx] == 0); - ret->type |= V_ASN1_NEG_INTEGER; - } - if (a != NULL) { - *a = ret; - } - } - } - - if (err != 0) { - wolfSSL_ASN1_INTEGER_free(ret); - ret = NULL; - } - - return ret; -} -#endif /* OPENSSL_EXTRA */ - -#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -/* Used to create a new WOLFSSL_ASN1_INTEGER structure. - * returns a pointer to new structure on success and NULL on failure - */ -WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void) -{ - WOLFSSL_ASN1_INTEGER* a; - - a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, - DYNAMIC_TYPE_OPENSSL); - if (a == NULL) { - return NULL; - } - - XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER)); - a->data = a->intData; - a->isDynamic = 0; - a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; - a->length = 0; - return a; -} - - -/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */ -void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) -{ - if (in != NULL) { - if (in->isDynamic) { - XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL); - } - XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL); - } -} - - -/* Duplicate all WOLFSSL_ASN1_INTEGER members from src to dup - * src : WOLFSSL_ASN1_INTEGER to duplicate - * Returns pointer to duplicate WOLFSSL_ASN1_INTEGER - */ -WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src) -{ - WOLFSSL_ASN1_INTEGER* copy; - WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup"); - if (!src) - return NULL; - - copy = wolfSSL_ASN1_INTEGER_new(); - - if (copy == NULL) - return NULL; - - copy->negative = src->negative; - copy->dataMax = src->dataMax; - copy->isDynamic = src->isDynamic; -#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) - copy->length = src->length; -#endif - XSTRNCPY((char*)copy->intData,(const char*)src->intData,WOLFSSL_ASN1_INTEGER_MAX); - - if (copy->isDynamic && src->data && copy->dataMax) { - copy->data = (unsigned char*) - XMALLOC(src->dataMax,NULL,DYNAMIC_TYPE_OPENSSL); - if (copy->data == NULL) { - wolfSSL_ASN1_INTEGER_free(copy); - return NULL; - } - XMEMCPY(copy->data, src->data, copy->dataMax); - } - return copy; -} - - -/* sets the value of WOLFSSL_ASN1_INTEGER a to the long value v. */ -int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v) -{ - int ret = WOLFSSL_SUCCESS; /* return 1 for success and 0 for failure */ - int j; - unsigned int i = 0; - unsigned char tmp[sizeof(long)+1] = {0}; - int pad = 0; - - if (a != NULL) { - /* dynamically create data buffer, +2 for type and length */ - a->data = (unsigned char*)XMALLOC((sizeof(long)+1) + 2, NULL, - DYNAMIC_TYPE_OPENSSL); - if (a->data == NULL) { - wolfSSL_ASN1_INTEGER_free(a); - ret = WOLFSSL_FAILURE; - } - else { - a->dataMax = (int)(sizeof(long)+1) + 2; - a->isDynamic = 1; - } - } - else { - /* Invalid parameter */ - ret = WOLFSSL_FAILURE; - } - - - if (ret != WOLFSSL_FAILURE) { - /* Set type */ - a->data[i++] = ASN_INTEGER; - - /* Check for negative */ - if (v < 0) { - a->negative = 1; - v *= -1; - } - - /* Create char buffer */ - for (j = 0; j < (int)sizeof(long); j++) { - if (v == 0) { - break; - } - tmp[j] = (unsigned char)(v & 0xff); - v >>= 8; - } - - /* 0 pad to indicate positive number when top bit set. */ - if ((!a->negative) && (j > 0) && (tmp[j-1] & 0x80)) { - pad = 1; - } - /* Set length */ - a->data[i++] = (unsigned char)(((j == 0) ? ++j : j) + pad); - /* +2 for type and length */ - a->length = j + pad + 2; - - /* Add padding if required. */ - if (pad) { - a->data[i++] = 0; - } - /* Copy to data */ - for (; j > 0; j--) { - a->data[i++] = tmp[j-1]; - } - } - - return ret; -} - -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ - -#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) -#ifndef NO_ASN_TIME -#ifndef NO_BIO -int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) -{ - char buf[MAX_TIME_STRING_SZ]; - int ret = WOLFSSL_SUCCESS; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); - - if (bio == NULL || asnTime == NULL) { - WOLFSSL_MSG("NULL function argument"); - return WOLFSSL_FAILURE; - } - - if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, - sizeof(buf)) == NULL) { - XMEMSET(buf, 0, MAX_TIME_STRING_SZ); - XSTRNCPY(buf, "Bad time value", sizeof(buf)-1); - ret = WOLFSSL_FAILURE; - } - - if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) { - WOLFSSL_MSG("Unable to write to bio"); - return WOLFSSL_FAILURE; - } - - return ret; -} -#endif /* !NO_BIO */ - -char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) -{ - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); - - if (t == NULL || buf == NULL || len < 5) { - WOLFSSL_MSG("Bad argument"); - return NULL; - } - - if (t->length > len) { - WOLFSSL_MSG("Length of date is longer then buffer"); - return NULL; - } - - if (!GetTimeString(t->data, t->type, buf, len)) { - return NULL; - } - - return buf; -} - -/* Converts a WOLFSSL_ASN1_TIME to a struct tm. Returns WOLFSSL_SUCCESS on - * success and WOLFSSL_FAILURE on failure. */ -static int Asn1TimeToTm(WOLFSSL_ASN1_TIME* asnTime, struct tm* tm) -{ - unsigned char* asn1TimeBuf; - int asn1TimeBufLen; - int i = 0; - int bytesNeeded = 11; - - if (asnTime == NULL) { - WOLFSSL_MSG("asnTime is NULL"); - return WOLFSSL_FAILURE; - } - if (tm == NULL) { - WOLFSSL_MSG("tm is NULL"); - return WOLFSSL_FAILURE; - } - - asn1TimeBuf = wolfSSL_ASN1_TIME_get_data(asnTime); - if (asn1TimeBuf == NULL) { - WOLFSSL_MSG("Failed to get WOLFSSL_ASN1_TIME buffer."); - return WOLFSSL_FAILURE; - } - asn1TimeBufLen = wolfSSL_ASN1_TIME_get_length(asnTime); - if (asn1TimeBufLen <= 0) { - WOLFSSL_MSG("Failed to get WOLFSSL_ASN1_TIME buffer length."); - return WOLFSSL_FAILURE; - } - XMEMSET(tm, 0, sizeof(struct tm)); - - /* Convert ASN1_time to struct tm */ - /* Check type */ - if (asnTime->type == ASN_UTC_TIME) { - /* 2-digit year */ - bytesNeeded += 2; - if (bytesNeeded > asn1TimeBufLen) { - WOLFSSL_MSG("WOLFSSL_ASN1_TIME buffer length is invalid."); - return WOLFSSL_FAILURE; - } - if (asn1TimeBuf[bytesNeeded-1] != 'Z') { - WOLFSSL_MSG("Expecting UTC time."); - return WOLFSSL_FAILURE; - } - - tm->tm_year = (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_year += asn1TimeBuf[i] - '0'; i++; - if (tm->tm_year < 70) { - tm->tm_year += 100; - } - } - else if (asnTime->type == ASN_GENERALIZED_TIME) { - /* 4-digit year */ - bytesNeeded += 4; - if (bytesNeeded > asn1TimeBufLen) { - WOLFSSL_MSG("WOLFSSL_ASN1_TIME buffer length is invalid."); - return WOLFSSL_FAILURE; - } - if (asn1TimeBuf[bytesNeeded-1] != 'Z') { - WOLFSSL_MSG("Expecting UTC time."); - return WOLFSSL_FAILURE; - } - - tm->tm_year = (asn1TimeBuf[i] - '0') * 1000; i++; - tm->tm_year += (asn1TimeBuf[i] - '0') * 100; i++; - tm->tm_year += (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_year += asn1TimeBuf[i] - '0'; i++; - tm->tm_year -= 1900; - } - else { - WOLFSSL_MSG("asnTime->type is invalid."); - return WOLFSSL_FAILURE; - } - - tm->tm_mon = (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_mon += (asn1TimeBuf[i] - '0') - 1; i++; /* January is 0 not 1 */ - tm->tm_mday = (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_mday += (asn1TimeBuf[i] - '0'); i++; - tm->tm_hour = (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_hour += (asn1TimeBuf[i] - '0'); i++; - tm->tm_min = (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_min += (asn1TimeBuf[i] - '0'); i++; - tm->tm_sec = (asn1TimeBuf[i] - '0') * 10; i++; - tm->tm_sec += (asn1TimeBuf[i] - '0'); - -#ifdef XMKTIME - /* Call XMKTIME on tm to get the tm_wday and tm_yday fields populated. */ - XMKTIME(tm); -#endif - - return WOLFSSL_SUCCESS; -} - -int wolfSSL_ASN1_TIME_to_tm(const WOLFSSL_ASN1_TIME* asnTime, struct tm* tm) -{ - time_t currentTime; - struct tm *tmpTs; -#if defined(NEED_TMP_TIME) - /* for use with gmtime_r */ - struct tm tmpTimeStorage; - tmpTs = &tmpTimeStorage; -#else - tmpTs = NULL; -#endif - (void)tmpTs; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_tm"); - - /* If asnTime is NULL, then the current time is converted. */ - if (asnTime == NULL) { - if (tm == NULL) { - WOLFSSL_MSG("asnTime and tm are both NULL"); - return WOLFSSL_FAILURE; - } - - currentTime = wc_Time(0); - if (currentTime <= 0) { - WOLFSSL_MSG("Failed to get current time."); - return WOLFSSL_FAILURE; - } - - tm = XGMTIME(¤tTime, tmpTs); - if (tm == NULL) { - WOLFSSL_MSG("Failed to convert current time to UTC."); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; - } - - /* If tm is NULL this function performs a format check on asnTime only. */ - if (tm == NULL) { - return wolfSSL_ASN1_TIME_check(asnTime); - } - - return Asn1TimeToTm((WOLFSSL_ASN1_TIME*)asnTime, tm); -} -#endif /* !NO_ASN_TIME */ -#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY || - OPENSSL_EXTRA*/ - - -#ifdef OPENSSL_EXTRA - -int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, - const WOLFSSL_ASN1_INTEGER* b) -{ - int ret = 0; - - WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_cmp"); - - if (a == NULL || b == NULL) { - WOLFSSL_MSG("Bad parameter."); - ret = WOLFSSL_FATAL_ERROR; - } - - if (ret == 0 && ((a->length != b->length) || - ((a->negative == 0) != (b->negative == 0)))) { - ret = WOLFSSL_FATAL_ERROR; - } - if (ret == 0) { - ret = XMEMCMP(a->data, b->data, a->length); - } - - WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_cmp", ret); - - return ret; -} - -long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* a) -{ - long ret = 1; - WOLFSSL_BIGNUM* bn = NULL; - - WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_get"); - - if (a == NULL) { - /* OpenSSL returns 0 when a is NULL and -1 if there is an error. Quoting - * the documentation: - * - * "ASN1_INTEGER_get() also returns the value of a but it returns 0 if a - * is NULL and -1 on error (which is ambiguous because -1 is a - * legitimate value for an ASN1_INTEGER). New applications should use - * ASN1_INTEGER_get_int64() instead." - * */ - ret = 0; - } - - if (ret > 0) { - bn = wolfSSL_ASN1_INTEGER_to_BN(a, NULL); - if (bn == NULL) { - ret = -1; - } - } - if (ret > 0) { - ret = wolfSSL_BN_get_word(bn); - if (a->negative == 1) { - ret = -ret; - } - } - - if (bn != NULL) { - wolfSSL_BN_free(bn); - } - - WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_get", (int)ret); - - return ret; -} - -#endif /* OPENSSL_EXTRA */ - #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) /* Gets an index to store SSL structure at. * @@ -24771,105 +23586,6 @@ long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) } #endif -#if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \ - || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) -/** - * Set `a` in a smart way. - * - * @param a Object to set - * @param type The type of object in value - * @param value Object to set - */ -void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value) -{ - if (!a) { - return; - } - switch (type) { - case V_ASN1_NULL: - a->value.ptr = (char *)value; - break; - case V_ASN1_SEQUENCE: - a->value.asn1_string = (WOLFSSL_ASN1_STRING*)value; - break; - case V_ASN1_OBJECT: - a->value.object = (WOLFSSL_ASN1_OBJECT*)value; - break; - case V_ASN1_UTCTIME: - a->value.utctime = (WOLFSSL_ASN1_TIME*)value; - break; - case V_ASN1_GENERALIZEDTIME: - a->value.generalizedtime = (WOLFSSL_ASN1_TIME*)value; - break; - default: - WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE"); - return; - } - a->type = type; -} - -#endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY || WOLFSSL_WPAS */ - -#if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) \ - || defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) \ - || defined(OPENSSL_EXTRA) -/** - * Allocate a new WOLFSSL_ASN1_TYPE object. - * - * @return New zero'ed WOLFSSL_ASN1_TYPE object - */ -WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void) -{ - WOLFSSL_ASN1_TYPE* ret = (WOLFSSL_ASN1_TYPE*)XMALLOC(sizeof(WOLFSSL_ASN1_TYPE), - NULL, DYNAMIC_TYPE_OPENSSL); - if (!ret) - return NULL; - XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TYPE)); - return ret; -} - -/** - * Free WOLFSSL_ASN1_TYPE and all its members. - * - * @param at Object to free - */ -void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at) -{ - if (at) { - switch (at->type) { - case V_ASN1_OBJECT: - wolfSSL_ASN1_OBJECT_free(at->value.object); - break; - case V_ASN1_UTCTIME: - #ifndef NO_ASN_TIME - wolfSSL_ASN1_TIME_free(at->value.utctime); - #endif - break; - case V_ASN1_GENERALIZEDTIME: - #ifndef NO_ASN_TIME - wolfSSL_ASN1_TIME_free(at->value.generalizedtime); - #endif - break; - case V_ASN1_UTF8STRING: - case V_ASN1_PRINTABLESTRING: - case V_ASN1_T61STRING: - case V_ASN1_IA5STRING: - case V_ASN1_UNIVERSALSTRING: - case V_ASN1_SEQUENCE: - wolfSSL_ASN1_STRING_free(at->value.asn1_string); - break; - default: - WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE"); - break; - } - XFREE(at, NULL, DYNAMIC_TYPE_OPENSSL); - } -} -#endif /* OPENSSL_ALL || WOLFSSL_APACHE_HTTPD || WOLFSSL_HAPROXY || WOLFSSL_WPAS - || OPENSSL_EXTRA */ - - - #ifndef NO_WOLFSSL_STUB /*** TBD ***/ WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) @@ -24880,221 +23596,6 @@ WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) } #endif -/** - * Get a textual representation of given WOLFSSL_ASN1_OBJECT then write it to - * buf at most buf_len bytes. - * - * params - * - buf: buffer where the textual representation is to be written to - * - buf_len: buffer size in bytes - * - a: WOLFSSL_ASN1_OBJECT - * - * return the string length written on success, WOLFSSL_FAILURE on failure. - */ -int wolfSSL_i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) -{ - WOLFSSL_ENTER("wolfSSL_i2t_ASN1_OBJECT"); - return wolfSSL_OBJ_obj2txt(buf, buf_len, a, 0); -} - -WOLFSSL_ASN1_OBJECT *wolfSSL_d2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a, - const unsigned char **der, - long length) -{ - const unsigned char *d; - long len; - int tag, cls; - WOLFSSL_ASN1_OBJECT* ret = NULL; - - WOLFSSL_ENTER("wolfSSL_d2i_ASN1_OBJECT"); - - if (!der || !*der || length <= 0) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - - d = *der; - - if (wolfSSL_ASN1_get_object(&d, &len, &tag, &cls, length) & 0x80) { - WOLFSSL_MSG("wolfSSL_ASN1_get_object error"); - return NULL; - } - /* d now points to value */ - - if (tag != ASN_OBJECT_ID) { - WOLFSSL_MSG("Not an ASN object"); - return NULL; - } - - ret = wolfSSL_c2i_ASN1_OBJECT(a, &d, len); - if (ret) - *der = d; - return ret; -} - -/** - * Parse an ASN1 encoded input and output information about the parsed object - * @param in ASN1 encoded data. *in is moved to the value of the ASN1 object - * @param len Length of parsed ASN1 object - * @param tag Tag value of parsed ASN1 object - * @param cls Class of parsed ASN1 object - * @param inLen Length of *in buffer - * @return int Depends on which bits are set in the returned int: - * 0x80 an error occurred during parsing - * 0x20 parsed object is constructed - * 0x01 the parsed object length is infinite - */ -int wolfSSL_ASN1_get_object(const unsigned char **in, long *len, int *tag, - int *cls, long inLen) -{ - word32 inOutIdx = 0; - int l; - byte t; - int ret = 0x80; - - WOLFSSL_ENTER("wolfSSL_ASN1_get_object"); - - if (!in || !*in || !len || !tag || !cls || inLen == 0) { - WOLFSSL_MSG("Bad parameter"); - return ret; - } - - if (GetASNTag(*in, &inOutIdx, &t, (word32)inLen) != 0) { - WOLFSSL_MSG("GetASNTag error"); - return ret; - } - - if (GetLength(*in, &inOutIdx, &l, (word32)inLen) < 0) { - WOLFSSL_MSG("GetLength error"); - return ret; - } - - *tag = t & 0x1F; /* Tag number is 5 lsb */ - *cls = t & 0xC0; /* Class is 2 msb */ - *len = l; - ret = t & ASN_CONSTRUCTED; - - if (l > (int)(inLen - inOutIdx)) { - /* Still return other values but indicate error in msb */ - ret |= 0x80; - } - - *in += inOutIdx; - return ret; -} - -WOLFSSL_ASN1_OBJECT *wolfSSL_c2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a, - const unsigned char **pp, long len) -{ - WOLFSSL_ASN1_OBJECT* ret = NULL; - - WOLFSSL_ENTER("wolfSSL_c2i_ASN1_OBJECT"); - - if (!pp || !*pp || len <= 0) { - WOLFSSL_MSG("Bad parameter"); - return NULL; - } - - if (!(ret = wolfSSL_ASN1_OBJECT_new())) { - WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new error"); - return NULL; - } - - ret->obj = (const unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1); - if (!ret->obj) { - WOLFSSL_MSG("error allocating asn data memory"); - wolfSSL_ASN1_OBJECT_free(ret); - return NULL; - } - - XMEMCPY((byte*)ret->obj, *pp, len); - ret->objSz = (unsigned int)len; - ret->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; - - *pp += len; - - if (a) - *a = ret; - return ret; -} - -#ifndef NO_BIO -/* Return number of bytes written to BIO on success. 0 on failure. */ -int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, WOLFSSL_ASN1_OBJECT *a) -{ - int length = 0; - word32 idx = 0; - const char null_str[] = "NULL"; - - WOLFSSL_ENTER("wolfSSL_i2a_ASN1_OBJECT"); - - if (bp == NULL) - return WOLFSSL_FAILURE; - - if (a == NULL) { - /* Write "NULL" */ - if (wolfSSL_BIO_write(bp, null_str, (int)XSTRLEN(null_str)) == - (int)XSTRLEN(null_str)) { - return (int)XSTRLEN(null_str); - } - else { - return WOLFSSL_FAILURE; - } - } - - - if ((a->obj == NULL) || (a->obj[idx++] != ASN_OBJECT_ID)) { - WOLFSSL_MSG("Bad ASN1 Object"); - return WOLFSSL_FAILURE; - } - - if (GetLength((const byte*)a->obj, &idx, &length, - a->objSz) < 0 || length < 0) { - return WOLFSSL_FAILURE; - } - - if (wolfSSL_BIO_write(bp, a->obj + idx, length) == (int)length) { - return length; - } - - return WOLFSSL_FAILURE; -} -#endif /* !NO_BIO */ - -/* Returns object data for an ASN1_OBJECT */ -/* If pp is NULL then only the size is returned */ -/* If pp has pointer to pointer then its used directly */ -/* If pp has pointer to pointer that is NULL then new variable is allocated */ -/* Failure returns WOLFSSL_FAILURE (0) */ -int wolfSSL_i2d_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT *a, unsigned char **pp) -{ - byte *p; - - WOLFSSL_ENTER("wolfSSL_i2d_ASN1_OBJECT"); - - if (!a || !a->obj) { - WOLFSSL_MSG("Bad parameters"); - return WOLFSSL_FAILURE; - } - - if (!pp) - return a->objSz; - - if (*pp) - p = *pp; - else { - p = (byte*)XMALLOC(a->objSz, NULL, DYNAMIC_TYPE_OPENSSL); - if (!p) { - WOLFSSL_MSG("Bad malloc"); - return WOLFSSL_FAILURE; - } - } - - XMEMCPY(p, a->obj, a->objSz); - *pp = p + a->objSz; - return a->objSz; -} - #ifndef NO_WOLFSSL_STUB /*** TBD ***/ void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, @@ -26216,289 +24717,6 @@ size_t wolfSSL_CRYPTO_cts128_decrypt(const unsigned char *in, #endif /* HAVE_CTS */ #endif /* NO_AES */ -#ifndef NO_ASN_TIME -#ifndef NO_BIO -int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) -{ - WOLFSSL_ENTER("wolfSSL_ASN1_UTCTIME_print"); - if (bio == NULL || a == NULL) { - return WOLFSSL_FAILURE; - } - if (a->type != ASN_UTC_TIME) { - WOLFSSL_MSG("Error, not UTC_TIME"); - return WOLFSSL_FAILURE; - } - - return wolfSSL_ASN1_TIME_print(bio, a); -} - -#endif /* !NO_BIO */ - -/* Checks the ASN1 syntax of "a" - * returns WOLFSSL_SUCCESS (1) if correct otherwise WOLFSSL_FAILURE (0) */ -int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a) -{ - char buf[MAX_TIME_STRING_SZ]; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check"); - - /* if can parse the WOLFSSL_ASN1_TIME passed in then consider syntax good */ - if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf, - MAX_TIME_STRING_SZ) == NULL) { - return WOLFSSL_FAILURE; - } - return WOLFSSL_SUCCESS; -} - -/* - * Convert time to Unix time (GMT). - */ -static long long TimeToUnixTime(int sec, int minute, int hour, int mday, - int mon, int year) -{ - /* Number of cumulative days from the previous months, starting from - * beginning of January. */ - static const int monthDaysCumulative [12] = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 - }; - int leapDays = year; - - if (mon <= 1) { - --leapDays; - } - leapDays = leapDays / 4 - leapDays / 100 + leapDays / 400 - 1969 / 4 + - 1969 / 100 - 1969 / 400; - - return ((((long long) (year - 1970) * 365 + leapDays + - monthDaysCumulative[mon] + mday - 1) * 24 + hour) * 60 + minute) * - 60 + sec; -} - -int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from, - const WOLFSSL_ASN1_TIME *to) -{ - const int SECS_PER_DAY = 24 * 60 * 60; - struct tm fromTm_s, *fromTmGmt = &fromTm_s; - struct tm toTm_s, *toTmGmt = &toTm_s; - time_t currTime; - long long fromSecs; - long long toSecs; - double diffSecs; - struct tm *tmpTs; -#if defined(NEED_TMP_TIME) - /* for use with gmtime_r */ - struct tm tmpTimeStorage; - tmpTs = &tmpTimeStorage; -#else - tmpTs = NULL; -#endif - (void)tmpTs; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_diff"); - - if (days == NULL) { - WOLFSSL_MSG("days is NULL"); - return WOLFSSL_FAILURE; - } - if (secs == NULL) { - WOLFSSL_MSG("secs is NULL"); - return WOLFSSL_FAILURE; - } - - if (from == NULL && to == NULL) { - *days = 0; - *secs = 0; - return WOLFSSL_SUCCESS; - } - - if (from == NULL) { - currTime = wc_Time(0); - fromTmGmt = XGMTIME(&currTime, tmpTs); - if (fromTmGmt == NULL) { - WOLFSSL_MSG("XGMTIME for from time failed."); - return WOLFSSL_FAILURE; - } - } - else if (wolfSSL_ASN1_TIME_to_tm(from, fromTmGmt) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to convert from time to struct tm."); - return WOLFSSL_FAILURE; - } - - /* We use TimeToUnixTime here instead of XMKTIME to avoid the Year 2038 - * Problem on platforms where time_t is 32 bits. struct tm stores the year - * as years since 1900, so we add 1900 to the year. */ - fromSecs = TimeToUnixTime(fromTmGmt->tm_sec, fromTmGmt->tm_min, - fromTmGmt->tm_hour, fromTmGmt->tm_mday, - fromTmGmt->tm_mon, fromTmGmt->tm_year + 1900); - - if (to == NULL) { - currTime = wc_Time(0); - toTmGmt = XGMTIME(&currTime, tmpTs); - if (toTmGmt == NULL) { - WOLFSSL_MSG("XGMTIME for to time failed."); - return WOLFSSL_FAILURE; - } - } - else if (wolfSSL_ASN1_TIME_to_tm(to, toTmGmt) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to convert to time to struct tm."); - return WOLFSSL_FAILURE; - } - - toSecs = TimeToUnixTime(toTmGmt->tm_sec, toTmGmt->tm_min, toTmGmt->tm_hour, - toTmGmt->tm_mday, toTmGmt->tm_mon, - toTmGmt->tm_year + 1900); - - diffSecs = (double)(toSecs - fromSecs); - *days = (int) (diffSecs / SECS_PER_DAY); - *secs = (int) (diffSecs - (((double)*days) * SECS_PER_DAY)); - - return WOLFSSL_SUCCESS; -} - -int wolfSSL_ASN1_TIME_compare(const WOLFSSL_ASN1_TIME *a, - const WOLFSSL_ASN1_TIME *b) -{ - int ret; - int days; - int secs; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_compare"); - - if (wolfSSL_ASN1_TIME_diff(&days, &secs, a, b) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Failed to get time difference."); - ret = -2; - } - else { - if (days == 0 && secs == 0) { - /* a and b are the same time. */ - ret = 0; - } - else if (days >= 0 && secs >= 0) { - /* a is before b. */ - ret = -1; - } - else if (days <= 0 && secs <= 0) { - /* a is after b. */ - ret = 1; - } - else { - WOLFSSL_MSG("Incoherent time difference."); - ret = -2; - } - } - - WOLFSSL_LEAVE("wolfSSL_ASN1_TIME_compare", ret); - - return ret; -} -#endif /* !NO_ASN_TIME */ - -#ifndef NO_WOLFSSL_STUB -WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *s, time_t t) -{ - WOLFSSL_STUB("wolfSSL_ASN1_TIME_set"); - (void)s; - (void)t; - return s; -} -#endif /* !NO_WOLFSSL_STUB */ - -int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *s, const char *str) -{ - int slen; - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_set_string"); - - if (!str) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - slen = (int)XSTRLEN(str)+1; - if (slen > CTC_DATE_SIZE) { - WOLFSSL_MSG("Date string too long"); - return WOLFSSL_FAILURE; - } - if (s) { - XMEMCPY(s->data, str, slen); - s->length = slen - 1; /* do not include null terminator in length */ - s->type = slen == ASN_UTC_TIME_SIZE ? V_ASN1_UTCTIME : - V_ASN1_GENERALIZEDTIME; - } - return WOLFSSL_SUCCESS; -} - -#ifndef NO_BIO - -/* Return the month as a string. - * - * n The number of the month as a two characters (1 based). - * returns the month as a string. - */ -static WC_INLINE const char* MonthStr(const char* n) -{ - static const char monthStr[12][4] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1]; -} - -int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, - const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) -{ - const char* p; - WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); - - if (bio == NULL || asnTime == NULL) - return BAD_FUNC_ARG; - - if (asnTime->type != ASN_GENERALIZED_TIME) { - WOLFSSL_MSG("Error, not GENERALIZED_TIME"); - return WOLFSSL_FAILURE; - } - p = (const char *)(asnTime->data); - /* GetTimeString not always available. */ - if (wolfSSL_BIO_write(bio, MonthStr(p + 4), 3) <= 0) - return WOLFSSL_FAILURE; - if (wolfSSL_BIO_write(bio, " ", 1) <= 0) - return WOLFSSL_FAILURE; - - /* Day */ - if (wolfSSL_BIO_write(bio, p + 6, 2) <= 0) - return WOLFSSL_FAILURE; - if (wolfSSL_BIO_write(bio, " ", 1) <= 0) - return WOLFSSL_FAILURE; - - /* Hour */ - if (wolfSSL_BIO_write(bio, p + 8, 2) <= 0) - return WOLFSSL_FAILURE; - if (wolfSSL_BIO_write(bio, ":", 1) <= 0) - return WOLFSSL_FAILURE; - - /* Min */ - if (wolfSSL_BIO_write(bio, p + 10, 2) <= 0) - return WOLFSSL_FAILURE; - if (wolfSSL_BIO_write(bio, ":", 1) <= 0) - return WOLFSSL_FAILURE; - - /* Secs */ - if (wolfSSL_BIO_write(bio, p + 12, 2) <= 0) - return WOLFSSL_FAILURE; - if (wolfSSL_BIO_write(bio, " ", 1) <= 0) - return WOLFSSL_FAILURE; - if (wolfSSL_BIO_write(bio, p, 4) <= 0) - return WOLFSSL_FAILURE; - - return 0; -} -#endif /* !NO_BIO */ - -void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time) -{ - WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free"); - if (asn1Time == NULL) - return; - XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data)); -} - #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) @@ -26703,6 +24921,47 @@ void wolfSSL_sk_GENERIC_free(WOLFSSL_STACK* sk) wolfSSL_sk_free(sk); } +/* Pop off data from the stack. Checks that the type matches the stack type. + * + * @param [in, out] sk Stack of objects. + * @param [in] type Type of stack. + * @return Object on success. + * @return NULL when stack is NULL or no nodes left in stack. + */ +void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type) +{ + WOLFSSL_STACK* node; + void* data = NULL; + + /* Check we have a stack passed in of the right type. */ + if ((sk != NULL) && (sk->type == type)) { + /* Get the next node to become the new first node. */ + node = sk->next; + /* Get the ASN.1 OBJECT_ID object in the first node. */ + data = sk->data.generic; + + /* Check whether there is a next node. */ + if (node != NULL) { + /* Move content out of next node into current node. */ + sk->data.obj = node->data.obj; + sk->next = node->next; + /* Dispose of node. */ + XFREE(node, NULL, DYNAMIC_TYPE_ASN1); + } + else { + /* No more nodes - clear out data. */ + sk->data.obj = NULL; + } + + /* Decrement count as long as we thought we had nodes. */ + if (sk->num > 0) { + sk->num -= 1; + } + } + + return data; +} + /* Free all nodes in a stack including the pushed objects */ void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, wolfSSL_sk_freefunc func) @@ -26827,23 +25086,37 @@ void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, } } +/* Creates a new stack of the requested type. + * + * @param [in] type Type of stack. + * @return Empty stack on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type) +{ + WOLFSSL_STACK* sk; + + /* Allocate a new stack - first node. */ + sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (sk == NULL) { + WOLFSSL_MSG("WOLFSSL_STACK memory error"); + } + else { + /* Clear node and set type. */ + XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); + sk->type = type; + } + + return sk; +} + /* Creates and returns a new null stack. */ WOLFSSL_STACK* wolfSSL_sk_new_null(void) { - WOLFSSL_STACK* sk; WOLFSSL_ENTER("wolfSSL_sk_new_null"); - sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, - DYNAMIC_TYPE_OPENSSL); - if (sk == NULL) { - WOLFSSL_MSG("WOLFSSL_STACK memory error"); - return NULL; - } - - XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); - sk->type = STACK_TYPE_NULL; - - return sk; + return wolfssl_sk_new_type(STACK_TYPE_NULL); } int wolfSSL_sk_SSL_COMP_num(WOLF_STACK_OF(WOLFSSL_COMP)* sk) @@ -27896,301 +26169,6 @@ const WOLFSSL_ObjectInfo wolfssl_object_info[] = { const size_t wolfssl_object_info_sz = WOLFSSL_OBJECT_INFO_SZ; #endif -#ifdef OPENSSL_EXTRA - -WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, WOLFSSL_ASN1_INTEGER *ai) -{ - WOLFSSL_ASN1_INTEGER* a; - int len; - const int extraTagSz = MAX_LENGTH_SZ + 1; - byte intTag[MAX_LENGTH_SZ + 1]; - int idx = 0; - WOLFSSL_ENTER("wolfSSL_BN_to_ASN1_INTEGER"); - - if (ai == NULL) { - a = wolfSSL_ASN1_INTEGER_new(); - - if (a == NULL) - return NULL; - - a->type = V_ASN1_INTEGER; - } - else { - a = ai; - } - if (a) { - if (wolfSSL_BN_is_negative(bn) && !wolfSSL_BN_is_zero(bn)) { - a->type |= V_ASN1_NEG_INTEGER; - a->negative = 1; - } - - len = wolfSSL_BN_num_bytes(bn); - if (len == 0) - len = 1; - - /* allocate buffer */ - if (len + extraTagSz > (int)sizeof(a->intData)) { - /* create new data buffer and copy over */ - a->data = (byte*)XMALLOC(len + extraTagSz, NULL, - DYNAMIC_TYPE_OPENSSL); - if (a->data == NULL) { - if (a != ai) - wolfSSL_ASN1_INTEGER_free(a); - return NULL; - } - a->isDynamic = 1; - } - else { - XMEMSET(a->intData, 0, sizeof(a->intData)); - a->data = a->intData; - a->isDynamic = 0; - } - - /* populate data */ - if (wolfSSL_BN_is_zero(bn)) { - a->data[0] = 0; - } - else { - len = wolfSSL_BN_bn2bin(bn, a->data); - if (len < 0) { - wolfSSL_ASN1_INTEGER_free(a); - return NULL; - } - } - a->length = len; - - /* Write ASN tag */ - idx = SetASNInt(a->length, a->data[0], intTag); - XMEMMOVE(a->data + idx, a->data, a->length); - XMEMCPY(a->data, intTag, idx); - a->dataMax = a->length += idx; - } - - return a; -} - -#ifdef OPENSSL_ALL -void *wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM *tpl) -{ - void *ret = NULL; - const WOLFSSL_ASN1_TEMPLATE *member = NULL; - size_t i; - WOLFSSL_ENTER("wolfSSL_ASN1_item_new"); - if (!tpl) { - return NULL; - } - if (!(ret = (void *)XMALLOC(tpl->size, NULL, DYNAMIC_TYPE_OPENSSL))) { - return NULL; - } - XMEMSET(ret, 0, tpl->size); - for (member = tpl->members, i = 0; i < tpl->mcount; - member++, i++) { - switch (member->type) { - case WOLFSSL_X509_ALGOR_ASN1: - { - WOLFSSL_X509_ALGOR* algor = wolfSSL_X509_ALGOR_new(); - if (!algor) { - goto error; - } - *(WOLFSSL_X509_ALGOR**)(((byte*)ret) + member->offset) = algor; - break; - } - case WOLFSSL_ASN1_BIT_STRING_ASN1: - { - WOLFSSL_ASN1_BIT_STRING* bit_str = wolfSSL_ASN1_BIT_STRING_new(); - if (!bit_str) { - goto error; - } - *(WOLFSSL_ASN1_BIT_STRING**)(((byte*)ret) + member->offset) = bit_str; - break; - } - default: - WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_new"); - goto error; - } - } - return ret; -error: - wolfSSL_ASN1_item_free(ret, tpl); - return NULL; -} - -void wolfSSL_ASN1_item_free(void *val, const WOLFSSL_ASN1_ITEM *tpl) -{ - const WOLFSSL_ASN1_TEMPLATE *member = NULL; - size_t i; - WOLFSSL_ENTER("wolfSSL_ASN1_item_free"); - if (val) { - for (member = tpl->members, i = 0; i < tpl->mcount; - member++, i++) { - switch (member->type) { - case WOLFSSL_X509_ALGOR_ASN1: - { - WOLFSSL_X509_ALGOR* algor = *(WOLFSSL_X509_ALGOR**) - (((byte*)val) + member->offset); - if (algor) { - wolfSSL_X509_ALGOR_free(algor); - } - break; - } - case WOLFSSL_ASN1_BIT_STRING_ASN1: - { - WOLFSSL_ASN1_BIT_STRING* bit_str = *(WOLFSSL_ASN1_BIT_STRING**) - (((byte*)val) + member->offset); - if (bit_str) { - wolfSSL_ASN1_BIT_STRING_free(bit_str); - } - break; - } - default: - WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_free"); - } - } - XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL); - } -} - -#define bufLenOrNull(buf, len) ((buf) ? (buf) + (len) : NULL) - -static int i2dProcessMembers(const void *src, byte *buf, - const WOLFSSL_ASN1_TEMPLATE *members, size_t mcount) -{ - const WOLFSSL_ASN1_TEMPLATE *member = NULL; - int len = 0, ret; - size_t i; - WOLFSSL_ENTER("i2dProcessMembers"); - for (member = members, i = 0; i < mcount; member++, i++) { - switch (member->type) { - case WOLFSSL_X509_ALGOR_ASN1: - { - word32 oid = 0; - word32 idx = 0; - const WOLFSSL_X509_ALGOR* algor = *(const WOLFSSL_X509_ALGOR**) - (((byte*)src) + member->offset); - if (!algor->algorithm) { - WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE); - return WOLFSSL_FAILURE; - } - - if (GetObjectId(algor->algorithm->obj, &idx, &oid, - algor->algorithm->grp, algor->algorithm->objSz) < 0) { - WOLFSSL_MSG("Issue getting OID of object"); - return -1; - } - - ret = SetAlgoID(oid, bufLenOrNull(buf, len), - algor->algorithm->grp, 0); - if (!ret) { - return WOLFSSL_FAILURE; - } - len += ret; - break; - } - case WOLFSSL_ASN1_BIT_STRING_ASN1: - { - const WOLFSSL_ASN1_BIT_STRING* bit_str; - bit_str = *(const WOLFSSL_ASN1_BIT_STRING**) - (((byte*)src) + member->offset); - len += SetBitString(bit_str->length, 0, bufLenOrNull(buf, len)); - if (buf && bit_str->data) { - XMEMCPY(buf + len, bit_str->data, bit_str->length); - } - len += bit_str->length; - break; - } - default: - WOLFSSL_MSG("Type not support in processMembers"); - WOLFSSL_LEAVE("processMembers", WOLFSSL_FAILURE); - return WOLFSSL_FAILURE; - } - } - WOLFSSL_LEAVE("processMembers", len); - return len; -} - -static int wolfSSL_ASN1_item_i2d_1(const void *src, byte *buf, - const WOLFSSL_ASN1_ITEM *tpl, int *len) -{ - *len = 0; - - switch (tpl->type) { - case ASN_SEQUENCE: - { - int seq_len = i2dProcessMembers(src, NULL, tpl->members, - tpl->mcount); - if (seq_len == WOLFSSL_FAILURE) - return WOLFSSL_FAILURE; - *len += SetSequence(seq_len, bufLenOrNull(buf, *len)); - if (buf) { - if (i2dProcessMembers(src, bufLenOrNull(buf, *len), tpl->members, - tpl->mcount) != seq_len) { - WOLFSSL_MSG("Inconsistent sequence length"); - return WOLFSSL_FAILURE; - } - } - *len += seq_len; - break; - } - default: - WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_i2d"); - return WOLFSSL_FAILURE; - } - - return WOLFSSL_SUCCESS; -} - -int wolfSSL_ASN1_item_i2d(const void *src, byte **dest, - const WOLFSSL_ASN1_ITEM *tpl) -{ - int len; - byte *buf = NULL; - - WOLFSSL_ENTER("wolfSSL_ASN1_item_i2d"); - - if ((src == NULL) || (tpl == NULL)) - goto error; - - if (wolfSSL_ASN1_item_i2d_1(src, NULL, tpl, &len) != WOLFSSL_SUCCESS) - goto error; - - if (dest == NULL) { - WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_SUCCESS); - return len; - } - - if (*dest == NULL) { - buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1); - if (buf == NULL) - goto error; - } else - buf = *dest; - - if (wolfSSL_ASN1_item_i2d_1(src, buf, tpl, &len) != WOLFSSL_SUCCESS) - goto error; - - if (*dest == NULL) - *dest = buf; - else { - /* XXX *dest length is not checked because the user is responsible - * for providing a long enough buffer - */ - XMEMCPY(*dest, buf, len); - } - - WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", len); - return len; -error: - if (buf) { - XFREE(buf, NULL, DYNAMIC_TYPE_ASN1); - } - WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", WOLFSSL_FAILURE); - return WOLFSSL_FAILURE; -} - -#endif /* OPENSSL_ALL */ - -#endif /* OPENSSL_EXTRA */ - #ifdef OPENSSL_EXTRA WOLFSSL_HMAC_CTX* wolfSSL_HMAC_CTX_new(void) { @@ -30434,80 +28412,6 @@ void* wolfSSL_GetHKDFExtractCtx(WOLFSSL* ssl) #ifndef NO_CERTS #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) -/* Convert ASN1 input string into canonical ASN1 string */ -/* , which has the following rules: */ -/* convert to UTF8 */ -/* convert to lower case */ -/* multi-spaces collapsed */ -/* @param asn_out a pointer to ASN1_STRING to be converted */ -/* @param asn_in a pointer to input ASN1_STRING */ -/* @return WOLFSSL_SUCCESS on successful converted, otherwise <=0 error code*/ -int wolfSSL_ASN1_STRING_canon(WOLFSSL_ASN1_STRING* asn_out, - const WOLFSSL_ASN1_STRING* asn_in) -{ - char* dst; - char* src; - int i, len; - - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_canon"); - - /* sanity check */ - if (asn_out == NULL || asn_in == NULL) { - WOLFSSL_MSG("invalid function arguments"); - return BAD_FUNC_ARG; - } - - switch (asn_in->type) { - case MBSTRING_UTF8: - case V_ASN1_PRINTABLESTRING: - break; - default: - WOLFSSL_MSG("just copy string"); - return wolfSSL_ASN1_STRING_copy(asn_out, asn_in); - } - /* type is set as UTF8 */ - asn_out->type = MBSTRING_UTF8; - asn_out->length = wolfSSL_ASN1_STRING_to_UTF8( - (unsigned char**)&asn_out->data, (WOLFSSL_ASN1_STRING*)asn_in); - - if (asn_out->length < 0) { - return WOLFSSL_FAILURE; - } - /* point to the last */ - dst = asn_out->data + asn_out->length; - /* point to the start */ - src = asn_out->data; - - len = asn_out->length; - - /* trimming spaces at the head and tail */ - dst--; - for (; (len > 0 && XISSPACE((unsigned char)*dst)); len--) { - dst--; - } - for (; (len > 0 && XISSPACE((unsigned char)*src)); len--) { - src++; - } - - /* point to the start */ - dst = asn_out->data; - - for (i = 0; i < len; dst++, i++) { - if (!XISASCII(*src)) { - /* keep non-ascii code */ - *dst = *src++; - } else if ((*src) > 0 && XISSPACE((unsigned char)*src)) { - *dst = 0x20; /* space */ - /* remove the rest of spaces */ - while (XISSPACE((unsigned char)*++src) && i++ < len); - } else { - *dst = (char)XTOLOWER((unsigned char)*src++); - } - } - /* put actual length */ - asn_out->length = (int)(dst - asn_out->data); - return WOLFSSL_SUCCESS; -} #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) #if !defined(NO_FILESYSTEM) @@ -31156,6 +29060,9 @@ int wolfSSL_ASN1_STRING_canon(WOLFSSL_ASN1_STRING* asn_out, XMEMCPY(buf, desc, bufSz); } } + else { + bufSz = 0; + } buf[bufSz] = '\0'; @@ -34718,137 +32625,6 @@ WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) #endif /* NO_SESSION_CACHE */ -#ifndef NO_BIO -int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, - char *buf, int size) -{ - int readNextLine; - int lineLen; - int len; - byte isNumCheck; - word32 outLen; - const int extraTagSz = MAX_LENGTH_SZ + 1; - byte intTag[MAX_LENGTH_SZ + 1]; - int idx = 0; - - WOLFSSL_ENTER("wolfSSL_a2i_ASN1_INTEGER"); - - if (!bio || !asn1 || !buf || size <= 0) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - - /* Reset asn1 */ - if (asn1->isDynamic && asn1->data) { - XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); - } - XMEMSET(asn1->intData, 0, WOLFSSL_ASN1_INTEGER_MAX); - asn1->data = asn1->intData; - asn1->isDynamic = 0; - asn1->length = 0; - asn1->negative = 0; - asn1->type = V_ASN1_INTEGER; - - lineLen = wolfSSL_BIO_gets(bio, buf, size); - do { - readNextLine = 0; - if (lineLen <= 0) { - WOLFSSL_MSG("wolfSSL_BIO_gets error"); - return WOLFSSL_FAILURE; - } - while (lineLen && (buf[lineLen-1] == '\n' || buf[lineLen-1] == '\r')) - lineLen--; - if (buf[lineLen-1] == '\\') - readNextLine = 1; - /* Ignore none-hex chars at the end of the line */ - outLen = 1; - while (lineLen && Base16_Decode((byte*)buf + lineLen - 1, 1, - &isNumCheck, &outLen) == ASN_INPUT_E) - lineLen--; - if (!lineLen || lineLen % 2) { - WOLFSSL_MSG("Invalid line length"); - return WOLFSSL_FAILURE; - } - len = asn1->length + (lineLen/2); - /* Check if it will fit in static memory and - * save space for the ASN tag in front */ - if (len > (int)(WOLFSSL_ASN1_INTEGER_MAX - extraTagSz)) { - /* Allocate mem for data */ - if (asn1->isDynamic) { - byte* tmp = (byte*)XREALLOC(asn1->data, len + extraTagSz, NULL, - DYNAMIC_TYPE_OPENSSL); - if (!tmp) { - WOLFSSL_MSG("realloc error"); - return WOLFSSL_FAILURE; - } - asn1->data = tmp; - } - else { - /* Up to this point asn1->data pointed to asn1->intData. - * Now that the size has grown larger than intData can handle - * the asn1 structure moves to a dynamic type with isDynamic - * flag being set and asn1->data being malloc'd. */ - asn1->data = (byte*)XMALLOC(len + extraTagSz, NULL, - DYNAMIC_TYPE_OPENSSL); - if (!asn1->data) { - WOLFSSL_MSG("malloc error"); - return WOLFSSL_FAILURE; - } - asn1->isDynamic = 1; - XMEMCPY(asn1->data, asn1->intData, asn1->length); - } - } - len = lineLen/2; - if (Base16_Decode((byte*)buf, lineLen, asn1->data + asn1->length, - (word32*)&len) != 0) { - WOLFSSL_MSG("Base16_Decode error"); - return WOLFSSL_FAILURE; - } - asn1->length += len; - } while (readNextLine); - - /* Write ASN tag */ - idx = SetASNInt(asn1->length, asn1->data[0], intTag); - XMEMMOVE(asn1->data + idx, asn1->data, asn1->length); - XMEMCPY(asn1->data, intTag, idx); - asn1->dataMax = asn1->length += idx; - - return WOLFSSL_SUCCESS; -} - -int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) -{ - word32 idx = 1; - int len = 0; - byte buf[512]; - word32 bufLen = 512; - - WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); - - if (bp == NULL || a == NULL) - return WOLFSSL_FAILURE; - - /* Skip ASN.1 INTEGER (type) byte. */ - if (a->data[idx] == 0x80 || /* Indefinite length, can't determine length */ - GetLength(a->data, &idx, &len, a->length) < 0) { - return 0; - } - - /* Zero length integer is the value zero. */ - if (len == 0) { - return wolfSSL_BIO_write(bp, "00", 2); - } - - if (Base16_Encode(a->data + idx, len, buf, &bufLen) != 0 || - bufLen == 0) { - return 0; - } - - return wolfSSL_BIO_write(bp, buf, bufLen - 1); /* Don't write out NULL char */ -} -#endif /* !NO_BIO */ - - #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) /* Expected return values from implementations of OpenSSL ticket key callback. */ @@ -36606,81 +34382,6 @@ int oid2nid(word32 oid, int grp) return -1; } -#ifndef NO_ASN -WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, - WOLFSSL_BIGNUM *bn) -{ -#ifdef WOLFSSL_SMALL_STACK - mp_int* mpi = NULL; -#else - mp_int mpi[1]; -#endif - word32 idx = 0; - int ret; - - WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN"); - - if (ai == NULL) { - return NULL; - } - -#ifdef WOLFSSL_SMALL_STACK - mpi = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (mpi == NULL) { - return NULL; - } -#endif - - /* First get the magnitude of ASN1_INTEGER. */ - ret = GetInt(mpi, ai->data, &idx, ai->dataMax); - if (ret != 0) { - #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) - ret = mp_init(mpi); /* must init mpi */ - if (ret != MP_OKAY) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return NULL; - } - /* Serial number in QT starts at index 0 of data */ - if (mp_read_unsigned_bin(mpi, (byte*)ai->data, ai->length) != 0) { - mp_clear(mpi); - #ifdef WOLFSSL_SMALL_STACK - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return NULL; - } - #else - /* expecting ASN1 format for INTEGER */ - WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret); - #ifdef WOLFSSL_SMALL_STACK - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return NULL; - #endif - } - - /* Now get the sign of ASN1_INTEGER. */ - if (ai->negative) { - mp_setneg(mpi); - } - - /* mp_clear needs called because mpi is copied and causes memory leak with - * --disable-fastmath */ - ret = wolfssl_bn_set_value(&bn, mpi); - mp_clear(mpi); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); -#endif - - if (ret != WOLFSSL_SUCCESS) { - return NULL; - } - return bn; -} -#endif /* !NO_ASN */ - /* frees all nodes in the current threads error queue * * id thread id. ERR_remove_state is depreciated and id is ignored. The @@ -36697,409 +34398,6 @@ void wolfSSL_ERR_remove_state(unsigned long id) #endif /* OPENSSL_EXTRA */ -#ifndef OPENSSL_EXTRA_NO_BN -#define WOLFSSL_SSL_BN_INCLUDED -#include "src/ssl_bn.c" -#endif /* OPENSSL_EXTRA_NO_BN */ - -#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)) && \ - !defined(NO_ASN) -#ifndef NO_BIO -static int unprintable_char(char c) -{ - const unsigned char last_unprintable = 31; - const unsigned char LF = 10; - const unsigned char CR = 13; - - if (c <= last_unprintable && c != LF && c != CR) { - return 1; - } - return 0; -} - -int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str) -{ - int i; - - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_print"); - if (out == NULL || str == NULL) - return WOLFSSL_FAILURE; - - for (i=0; i < str->length; i++) { - if (unprintable_char(str->data[i])) { - str->data[i] = '.'; - } - } - - if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){ - return WOLFSSL_FAILURE; - } - - return str->length; -} -#endif /* !NO_BIO */ -#endif /* (WOLFSSL_QT || OPENSSL_ALL || OPENSSL_EXTRA) && !NO_ASN */ - -#if defined(OPENSSL_EXTRA) - -const char *wolfSSL_ASN1_tag2str(int tag) -{ - static const char *const tag_label[31] = { - "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL", - "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED", - "", "UTF8STRING", "", "", "", - "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", - "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", - "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING", - "", "BMPSTRING" - }; - - if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) - tag &= ~0x100; - if (tag < 0 || tag > 30) - return "(unknown)"; - return tag_label[tag]; -} - -#ifndef NO_BIO -static int check_esc_char(char c, char *esc) -{ - char *ptr; - - ptr = esc; - while(*ptr != 0){ - if (c == *ptr) - return 1; - ptr++; - } - return 0; -} - -int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, - unsigned long flags) -{ - size_t str_len = 0, type_len = 0; - unsigned char *typebuf = NULL; - const char *hash="#"; - - WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex"); - if (out == NULL || str == NULL) - return WOLFSSL_FAILURE; - - /* add ASN1 type tag */ - if (flags & ASN1_STRFLGS_SHOW_TYPE){ - const char *tag = wolfSSL_ASN1_tag2str(str->type); - /* colon len + tag len + null*/ - type_len = XSTRLEN(tag) + 2; - typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (typebuf == NULL){ - WOLFSSL_MSG("memory alloc failed."); - return WOLFSSL_FAILURE; - } - XMEMSET(typebuf, 0, type_len); - if (XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag) - >= (int)type_len) - { - WOLFSSL_MSG("Buffer overrun."); - return WOLFSSL_FAILURE; - } - type_len--; - } - - /* dump hex */ - if (flags & ASN1_STRFLGS_DUMP_ALL){ - char hex_tmp[4]; - char *str_ptr, *str_end; - - if (type_len > 0){ - if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){ - XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; - } - str_len += type_len; - } - if (wolfSSL_BIO_write(out, hash, 1) != 1){ - goto err_exit; - } - str_len++; - if (flags & ASN1_STRFLGS_DUMP_DER){ - ByteToHexStr((byte)str->type, &hex_tmp[0]); - ByteToHexStr((byte)str->length, &hex_tmp[2]); - if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){ - goto err_exit; - } - str_len += 4; - XMEMSET(hex_tmp, 0, 4); - } - - str_ptr = str->data; - str_end = str->data + str->length; - while (str_ptr < str_end){ - ByteToHexStr((byte)*str_ptr, &hex_tmp[0]); - if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){ - goto err_exit; - } - str_ptr++; - str_len += 2; - } - if (type_len > 0) - XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return (int)str_len; - } - - if (type_len > 0){ - if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){ - XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; - } - str_len += type_len; - } - - if (flags & ASN1_STRFLGS_ESC_2253){ - char esc_ch[] = "+;<>\\"; - char* esc_ptr; - - esc_ptr = str->data; - while (*esc_ptr != 0){ - if (check_esc_char(*esc_ptr, esc_ch)){ - if (wolfSSL_BIO_write(out,"\\", 1) != 1) - goto err_exit; - str_len++; - } - if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1) - goto err_exit; - str_len++; - esc_ptr++; - } - if (type_len > 0) - XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return (int)str_len; - } - - if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){ - goto err_exit; - } - str_len += str->length; - if (type_len > 0) - XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - return (int)str_len; - -err_exit: - if (type_len > 0) - XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; -} -#endif /* !NO_BIO */ - -#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && !defined(TIME_OVERRIDES) - - -WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, - int offset_day, long offset_sec) -{ - const time_t sec_per_day = 24*60*60; - time_t t_adj = 0; - time_t offset_day_sec = 0; - char time_str[MAX_TIME_STRING_SZ]; - int time_get; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj"); - - if (s == NULL) { - s = wolfSSL_ASN1_TIME_new(); - if (s == NULL) { - return NULL; - } - } - - /* compute GMT time with offset */ - offset_day_sec = offset_day * sec_per_day; - t_adj = t + offset_day_sec + offset_sec; - - /* Get time string as either UTC or GeneralizedTime */ - time_get = GetFormattedTime(&t_adj, (byte*)time_str, - (word32)sizeof(time_str)); - if (time_get <= 0) { - wolfSSL_ASN1_TIME_free(s); - return NULL; - } - - if (wolfSSL_ASN1_TIME_set_string(s, time_str) != WOLFSSL_SUCCESS) { - wolfSSL_ASN1_TIME_free(s); - return NULL; - } - - return s; -} -#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES */ - -#ifndef NO_ASN_TIME - -WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void) -{ - WOLFSSL_ASN1_TIME* ret = (WOLFSSL_ASN1_TIME*) - XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, DYNAMIC_TYPE_OPENSSL); - if (!ret) - return NULL; - XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME)); - return ret; -} - -void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t) -{ - if (t) { - XFREE(t, NULL, DYNAMIC_TYPE_OPENSSL); - } -} -/* not a compatibility function - length getter for opaque type */ -int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t) -{ - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length"); - if (t == NULL) - return WOLFSSL_FAILURE; - return t->length; -} -/* not a compatibility function - data getter for opaque type */ -unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t) -{ - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data"); - if (t == NULL) - return NULL; - return t->data; -} - -WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, - WOLFSSL_ASN1_TIME **out) -{ - int time_type = 0; - WOLFSSL_ASN1_TIME *ret = NULL; - - WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime"); - if (t == NULL) { - WOLFSSL_MSG("Invalid ASN_TIME value"); - } else { - time_type = t->type; - if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){ - WOLFSSL_MSG("Invalid ASN_TIME type."); - } else { - if (out == NULL || *out == NULL) { - ret = wolfSSL_ASN1_TIME_new(); - if (ret == NULL){ - WOLFSSL_MSG("memory alloc failed."); - } - } else { - ret = *out; - } - } - } - - if (ret != NULL) { - if (time_type == ASN_GENERALIZED_TIME){ - XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE); - } else { /* ASN_UTC_TIME */ - /* convert UTC to generalized time */ - ret->type = ASN_GENERALIZED_TIME; - ret->length = ASN_GENERALIZED_TIME_SIZE; - if (t->data[0] >= '5') { - ret->data[0] = '1'; ret->data[1] = '9'; - } else { - ret->data[0] = '2'; ret->data[1] = '0'; - } - XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE); - } - } - - return ret; -} -#endif /* !NO_ASN_TIME */ - -#ifndef NO_ASN -int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp) -{ - unsigned char *pptr = NULL; - char pad = 0 ; - unsigned char pad_val = 0; - int ret_size = 0; - unsigned char data1 = 0; - unsigned char neg = 0; - int i = 0; - - WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER"); - if (a == NULL) - return WOLFSSL_FAILURE; - - ret_size = a->intData[1]; - if (ret_size == 0) - ret_size = 1; - else{ - ret_size = (int)a->intData[1]; - neg = a->negative; - data1 = a->intData[2]; - if (ret_size == 1 && data1 == 0) - neg = 0; - /* 0x80 or greater positive number in first byte */ - if (!neg && (data1 > 127)){ - pad = 1; - pad_val = 0; - } else if (neg){ - /* negative number */ - if (data1 > 128){ - pad = 1; - pad_val = 0xff; - } else if (data1 == 128){ - for (i = 3; i < a->intData[1] + 2; i++){ - if (a->intData[i]){ - pad = 1; - pad_val = 0xff; - break; - } - } - } - } - ret_size += (int)pad; - } - if (pp == NULL) - return ret_size; - - pptr = *pp; - if (pad) - *(pptr++) = pad_val; - if (a->intData[1] == 0) - *(pptr++) = 0; - else if (!neg){ - /* positive number */ - for (i=0; i < a->intData[1]; i++){ - *pptr = a->intData[i+2]; - pptr++; - } - } else { - /* negative number */ - int str_len = 0; - - /* 0 padding from end of buffer */ - str_len = (int)a->intData[1]; - pptr += a->intData[1] - 1; - while (!a->intData[str_len + 2] && str_len > 1){ - *(pptr--) = 0; - str_len--; - } - /* 2's complement next octet */ - *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1; - str_len--; - /* Complement any octets left */ - while (str_len > 0){ - *(pptr--) = a->intData[str_len + 1] ^ 0xff; - str_len--; - } - } - *pp += ret_size; - return ret_size; -} -#endif /* !NO_ASN */ -#endif /* OPENSSL_EXTRA */ - #ifdef OPENSSL_ALL #if !defined(NO_BIO) && !defined(NO_PWDBASED) && defined(HAVE_PKCS8) diff --git a/src/ssl_asn1.c b/src/ssl_asn1.c new file mode 100644 index 000000000..27ccd13c8 --- /dev/null +++ b/src/ssl_asn1.c @@ -0,0 +1,4026 @@ +/* ssl_asn1.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + + #include +#ifndef WC_NO_RNG + #include +#endif + +#if !defined(WOLFSSL_SSL_ASN1_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning ssl_asn1.c does not need to be compiled separately from ssl.c + #endif +#else + +/******************************************************************************* + * ASN1_item APIs + ******************************************************************************/ + +#ifdef OPENSSL_EXTRA + +#ifdef OPENSSL_ALL + +/* Create an ASN1 item of the specified type. + * + * @param [out] item Pointer to location to place new ASN1 item. + * @param [in] type Type of ASN1 item to create. + * @return 0 on success. + * @return 1 when item type not supported. + * @return 1 when item type allocation fails. + */ +static int wolfssl_asn1_item_new(void** item, int type) +{ + int err = 0; + + switch (type) { + case WOLFSSL_X509_ALGOR_ASN1: + *(WOLFSSL_X509_ALGOR**)item = wolfSSL_X509_ALGOR_new(); + break; + case WOLFSSL_ASN1_BIT_STRING_ASN1: + *(WOLFSSL_ASN1_BIT_STRING**)item = wolfSSL_ASN1_BIT_STRING_new(); + break; + default: + WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_new"); + *(void**)item = NULL; + } + /* Check whether an item was put in. */ + if (*(void**)item == NULL) { + err = 1; + } + + return err; +} + +/* Create a new ASN1 item based on a template. + * + * @param [in] tpl Template of ASN1 items. + * @return A new ASN1 item on success. + * @return NULL when tpl is NULL, dynamic memory allocation fails or ASN1 + * item type not supported. + */ +void* wolfSSL_ASN1_item_new(const WOLFSSL_ASN1_ITEM* tpl) +{ + int err = 0; + void* ret = NULL; + const WOLFSSL_ASN1_TEMPLATE *mem = NULL; + size_t i; + + WOLFSSL_ENTER("wolfSSL_ASN1_item_new"); + + if (tpl != NULL) { + ret = (void *)XMALLOC(tpl->size, NULL, DYNAMIC_TYPE_OPENSSL); + } + + if (ret != NULL) { + XMEMSET(ret, 0, tpl->size); + for (mem = tpl->members, i = 0; i < tpl->mcount; mem++, i++) { + if ((err = wolfssl_asn1_item_new( + (void**)(((byte*)ret) + mem->offset), mem->type))) { + break; + } + } + } + + if (err) { + wolfSSL_ASN1_item_free(ret, tpl); + ret = NULL; + } + return ret; +} + +/* Dispose of an ASN1 item of the specified type. + * + * @param [in, out] item Pointer to an anonymized ASN1 item to free. + * @param [in] type Type of ASN1 item to free. + */ +static void wolfssl_asn1_item_free(void** item, int type) +{ + switch (type) { + case WOLFSSL_X509_ALGOR_ASN1: + wolfSSL_X509_ALGOR_free(*(WOLFSSL_X509_ALGOR**)item); + break; + case WOLFSSL_ASN1_BIT_STRING_ASN1: + wolfSSL_ASN1_BIT_STRING_free(*(WOLFSSL_ASN1_BIT_STRING**)item); + break; + default: + WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_free"); + } +} + +/* Dispose of ASN1 item based on a template. + * + * @param [in, out] val ASN item to free. + * @param [in, tpl Template of ASN1 items. + */ +void wolfSSL_ASN1_item_free(void *items, const WOLFSSL_ASN1_ITEM *tpl) +{ + const WOLFSSL_ASN1_TEMPLATE *mem = NULL; + size_t i; + + WOLFSSL_ENTER("wolfSSL_ASN1_item_free"); + + if (items != NULL) { + for (mem = tpl->members, i = 0; i < tpl->mcount; mem++, i++) { + wolfssl_asn1_item_free((void**)(((byte*)items) + mem->offset), + mem->type); + } + } + XFREE(items, NULL, DYNAMIC_TYPE_OPENSSL); +} + +/* Offset buf if not NULL or NULL. */ +#define bufLenOrNull(buf, len) ((buf != NULL) ? ((buf) + (len)) : NULL) + +/* Encode X509 algorithm as DER. + * + * @param [in] algor X509 algorithm object. + * @param [in, out] buf Buffer to encode into. May be NULL. + * @return Length of DER encoding on success. + * @return 0 on failure. + */ +static int wolfSSL_i2d_X509_ALGOR(const WOLFSSL_X509_ALGOR* algor, byte* buf) +{ + int ret; + word32 oid = 0; + word32 idx = 0; + + if (algor->algorithm == 0) { + WOLFSSL_MSG("X509_ALGOR algorithm not set"); + ret = 0; + } + else if (GetObjectId(algor->algorithm->obj, &idx, &oid, + algor->algorithm->grp, algor->algorithm->objSz) < 0) { + WOLFSSL_MSG("Issue getting OID of object"); + ret = 0; + } + else { + ret = SetAlgoID(oid, buf, algor->algorithm->grp, 0); + } + + return ret; +} + +/* Encode ASN.1 BIT_STRING as DER. + * + * @param [in] bit_str BIT_STRING object. + * @param [in, out] buf Buffer to encode into. May be NULL. + * @return Length of DER encoding on success. + */ +static int wolfSSL_i2d_ASN1_BIT_STRING(const WOLFSSL_ASN1_BIT_STRING* bit_str, + byte* buf) +{ + int len; + + len = SetBitString(bit_str->length, 0, buf); + if ((buf != NULL) && (bit_str->data != NULL)) { + XMEMCPY(buf + len, bit_str->data, bit_str->length); + } + + return len + bit_str->length; +} + +/* Encode ASN item as DER. + * + * @param [in] item Pointer to anonymized ASN item. + * @param [in, out] buf Buffer to encode into. May be NULL. + * @return Length of DER encoding on success. + * @return 0 on failure. + */ +static int wolfssl_i2d_asn1_item(void** item, int type, byte* buf) +{ + int len; + + switch (type) { + case WOLFSSL_X509_ALGOR_ASN1: + len = wolfSSL_i2d_X509_ALGOR(*(const WOLFSSL_X509_ALGOR**)item, + buf); + break; + case WOLFSSL_ASN1_BIT_STRING_ASN1: + len = wolfSSL_i2d_ASN1_BIT_STRING( + *(const WOLFSSL_ASN1_BIT_STRING**)item, buf); + break; + default: + WOLFSSL_MSG("Type not support in processMembers"); + len = 0; + } + + return len; +} + +/* Encode members of an ASN.1 SEQUENCE as DER. + * + * @param [in] src ASN1 items to encode. + * @param [in, out] buf Buffer to encode into. May be NULL. + * @param [in] members ASN1 template members. + * @param [in] mcount Count of template members. + * @return Length of DER encoding on success. + * @return 0 on failure. + */ +static int wolfssl_i2d_asn1_items(const void* src, byte*buf, + const WOLFSSL_ASN1_TEMPLATE* members, size_t mcount) +{ + const WOLFSSL_ASN1_TEMPLATE* mem = NULL; + int len = 0; + int ret; + size_t i; + + WOLFSSL_ENTER("wolfssl_i2d_asn1_items"); + + for (mem = members, i = 0; i < mcount; mem++, i++) { + ret = wolfssl_i2d_asn1_item((void**)(((byte*)src) + mem->offset), + mem->type, bufLenOrNull(buf, len)); + if (ret == 0) { + len = 0; + break; + } + len += ret; + } + + WOLFSSL_LEAVE("wolfssl_i2d_asn1_items", len); + + return len; +} + +/* Encode sequence and items under it. + * + * @param [in] src ASN1 items to encode. + * @param [in, out] buf Buffer to encode into. May be NULL. + * @param [in] tpl Template of ASN1 items. + * @return Length of DER encoding on success. + * @return 0 on failure. + */ +static int i2d_ASN_SEQUENCE(const void* src, byte* buf, + const WOLFSSL_ASN1_ITEM* tpl) +{ + int seq_len; + int len = 0; + + seq_len = wolfssl_i2d_asn1_items(src, NULL, tpl->members, tpl->mcount); + if (seq_len != 0) { + len = SetSequence(seq_len, buf); + if (buf != NULL) { + wolfssl_i2d_asn1_items(src, buf + len, tpl->members, tpl->mcount); + } + len += seq_len; + } + + return len; +} + +/* Encode ASN1 template item. + * + * @param [in] src ASN1 items to encode. + * @param [in, out] buf Buffer to encode into. May be NULL. + * @param [in] tpl Template of ASN1 items. + * @return Length of DER encoding on success. + * @return 0 on failure. + */ +static int wolfssl_asn1_item_encode(const void* src, byte* buf, + const WOLFSSL_ASN1_ITEM* tpl) +{ + int len; + + switch (tpl->type) { + case ASN_SEQUENCE: + len = i2d_ASN_SEQUENCE(src, buf, tpl); + break; + default: + WOLFSSL_MSG("Type not supported in wolfSSL_ASN1_item_i2d"); + len = 0; + } + + return len; +} + +/* Encode ASN1 template. + * + * @param [in] src ASN1 items to encode. + * @param [in, out] dest Pointer to buffer to encode into. May be NULL. + * @param [in] tpl Template of ASN1 items. + * @return Length of DER encoding on success. + * @return 0 on failure. + */ +int wolfSSL_ASN1_item_i2d(const void* src, byte** dest, + const WOLFSSL_ASN1_ITEM* tpl) +{ + int ret = 1; + int len = 0; + byte* buf = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_item_i2d"); + + /* Validate parameters. */ + if ((src == NULL) || (tpl == NULL)) { + ret = 0; + } + + if ((ret == 1) && ((len = wolfssl_asn1_item_encode(src, NULL, tpl)) == 0)) { + ret = 0; + } + + if ((ret == 1) && (dest != NULL)) { + if (*dest == NULL) { + buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1); + if (buf == NULL) + ret = 0; + *dest = buf; + } + + if (ret == 1) { + len = wolfssl_asn1_item_encode(src, *dest, tpl); + } + } + + if (ret == 0) { + XFREE(buf, NULL, DYNAMIC_TYPE_ASN1); + len = 0; + } + WOLFSSL_LEAVE("wolfSSL_ASN1_item_i2d", len); + return len; +} + +#endif /* OPENSSL_ALL */ + +#endif /* OPENSSL_EXTRA */ + +/******************************************************************************* + * ASN1_BIT_STRING APIs + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +/* Create a new ASN.1 BIT_STRING object. + * + * @return ASN.1 BIT_STRING object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_BIT_STRING* wolfSSL_ASN1_BIT_STRING_new(void) +{ + WOLFSSL_ASN1_BIT_STRING* bitStr; + + bitStr = (WOLFSSL_ASN1_BIT_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_BIT_STRING), + NULL, DYNAMIC_TYPE_OPENSSL); + if (bitStr) { + XMEMSET(bitStr, 0, sizeof(WOLFSSL_ASN1_BIT_STRING)); + } + + return bitStr; +} + +/* Dispose of ASN.1 BIT_STRING object. + * + * Do not use bitStr after calling this function. + * + * @param [in, out] bitStr ASN.1 BIT_STRING to free. May be NULL. + */ +void wolfSSL_ASN1_BIT_STRING_free(WOLFSSL_ASN1_BIT_STRING* bitStr) +{ + if (bitStr != NULL) { + /* Dispose of any data allocated in BIT_STRING. */ + XFREE(bitStr->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + /* Dispose of the ASN.1 BIT_STRING object. */ + XFREE(bitStr, NULL, DYNAMIC_TYPE_OPENSSL); +} + +/* Get the value of the bit from the ASN.1 BIT_STRING at specified index. + * + * A NULL object a value of 0 for the bit at all indices. + * A negative index has a value of 0 for the bit. + * + * @param [in] bitStr ASN.1 BIT_STRING object. + * @param [in] i Index of bit. + * @return Value of bit. + */ +int wolfSSL_ASN1_BIT_STRING_get_bit(const WOLFSSL_ASN1_BIT_STRING* bitStr, + int i) +{ + int bit = 0; + + /* Check for data and whether index is in range. */ + if ((bitStr != NULL) && (bitStr->data != NULL) && (i >= 0) && + (bitStr->length > (i / 8))) { + bit = (bitStr->data[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0; + } + + return bit; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) + +/* Grow data to require length. + * + * @param [in] bitStr ASN.1 BIT_STRING object. + * @param [in] len Length, in bytes, of data required. + * @return 1 on success. + * @return 0 when dynamic memory allocation fails. + */ +static int wolfssl_asn1_bit_string_grow(WOLFSSL_ASN1_BIT_STRING* bitStr, + int len) +{ + int ret = 1; + byte* tmp; + + /* Realloc to length required. */ + tmp = (byte*)XREALLOC(bitStr->data, len, NULL, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + ret = 0; + } + else { + /* Clear out new, top bytes. */ + XMEMSET(tmp + bitStr->length, 0, len - bitStr->length); + bitStr->data = tmp; + bitStr->length = len; + } + + return ret; +} + +/* Set the value of a bit in the ASN.1 BIT_STRING at specified index. + * + * @param [in] bitStr ASN.1 BIT_STRING object. + * @param [in] idx Index of bit to set. + * @param [in] val Value of bit to set. Valid values: 0 or 1. + * @return 1 on success. + * @return 0 when bitStr is NULL, idx is negative, val is not 0 or 1, or + * dynamic memory allocation fails. + */ +int wolfSSL_ASN1_BIT_STRING_set_bit(WOLFSSL_ASN1_BIT_STRING* bitStr, int idx, + int val) +{ + int ret = 1; + int i = 0; + + /* Validate parameters. */ + if ((bitStr == NULL) || (idx < 0) || ((val != 0) && (val != 1))) { + ret = 0; + } + + if (ret == 1) { + i = idx / 8; + + /* Check if we need to extend data range. */ + if ((i >= bitStr->length) && (val != 0)) { + /* Realloc data to handle having bit set at index. */ + ret = wolfssl_asn1_bit_string_grow(bitStr, i + 1); + } + } + if ((ret == 1) && (i < bitStr->length)) { + /* Bit on at index. */ + byte bit = 1 << (7 - (idx % 8)); + + /* Clear bit and set to value. */ + bitStr->data[i] &= ~bit; + bitStr->data[i] |= bit & (byte)(0 - val); + } + + return ret; +} + +#endif /* OPENSSL_ALL && !NO_CERTS */ + +/******************************************************************************* + * ASN1_INTEGER APIs + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +/* Create a new empty ASN.1 INTEGER object. + * + * @return ASN.1 INTEGER object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void) +{ + WOLFSSL_ASN1_INTEGER* a; + + /* Allocate a new ASN.1 INTEGER object. */ + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a != NULL) { + XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER)); + /* Use fixed buffer field for data. */ + a->data = a->intData; + a->isDynamic = 0; + /* Maximum supported by fixed buffer. */ + a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; + /* No value set - no data. */ + a->length = 0; + } + + return a; +} + +/* Free the ASN.1 INTEGER object and any dynamically allocated data. + * + * @param [in, out] in ASN.1 INTEGER object. + */ +void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) +{ + if ((in != NULL) && (in->isDynamic)) { + /* Dispose of any data allocated in BIT_STRING. */ + XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + /* Dispose of the ASN.1 INTEGER object. */ + XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL); +} + +/* Reset the data of ASN.1 INTEGER object back to empty fixed array. + * + * @param [in] a ASN.1 INTEGER object. + */ +static void wolfssl_asn1_integer_reset_data(WOLFSSL_ASN1_INTEGER* a) +{ + /* Don't use dynamic buffer anymore. */ + if (a->isDynamic) { + /* Cache pointer to allocated data. */ + unsigned char* data = a->data; + /* No longer dynamic. */ + a->isDynamic = 0; + /* Point data at fixed array. */ + a->data = a->intData; + /* Set maximum length to fixed array size. */ + a->dataMax = (unsigned int)sizeof(a->intData); + /* Dispose of dynamically allocated data. */ + XFREE(data, NULL, DYNAMIC_TYPE_OPENSSL); + } + /* Clear out data from fixed array. */ + XMEMSET(a->intData, 0, sizeof(a->intData)); + /* No data, no length. */ + a->length = 0; + /* No data, not negative. */ + a->negative = 0; + /* Set type to positive INTEGER. */ + a->type = V_ASN1_INTEGER; +} + +/* Setup ASN.1 INTEGER object to handle data of required length. + * + * @param [in, out] a ASN.1 INTEGER object. + * @param [in] len Required length in bytes. + * @return 1 on success. + * @return 0 on dynamic memory allocation failure. + */ +static int wolfssl_asn1_integer_require_len(WOLFSSL_ASN1_INTEGER* a, int len, + int keepOldData) +{ + int ret = 1; + byte* data; + byte* oldData = a->intData; + int oldLen = a->length; + + if (a->isDynamic && (len > (int)a->dataMax)) { + oldData = a->data; + a->isDynamic = 0; + a->data = a->intData; + a->dataMax = (unsigned int)sizeof(a->intData); + } + a->length = 0; + if ((!a->isDynamic) && (len > (int)a->dataMax)) { + /* Create a new buffer to hold large integer value. */ + data = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (a->data == NULL) { + ret = 0; + } + else { + /* Indicate data is dynamic and copy data over. */ + a->isDynamic = 1; + a->data = data; + a->dataMax = len; + } + } + if (keepOldData) { + if (oldData != a->data) { + /* Copy old data into new buffer. */ + XMEMCPY(a->data, oldData, oldLen); + } + /* Restore old length. */ + a->length = oldLen; + } + if (oldData != a->intData) { + /* Dispose of the old dynamic data. */ + XFREE(oldData, NULL, DYNAMIC_TYPE_OPENSSL); + } + + return ret; +} + +/* Duplicate the ASN.1 INTEGER object into a newly allocated one. + * + * @param [in] src ASN.1 INTEGER object to copy. + * @return ASN.1 INTEGER object on success. + * @return NULL when src is NULL or dynamic memory allocation fails. + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup(const WOLFSSL_ASN1_INTEGER* src) +{ + WOLFSSL_ASN1_INTEGER* dup = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup"); + + /* Check for object to duplicate. */ + if (src != NULL) { + /* Create a new ASN.1 INTEGER object to be copied into. */ + dup = wolfSSL_ASN1_INTEGER_new(); + } + /* Check for object to copy into. */ + if (dup != NULL) { + /* Copy simple fields. */ + dup->length = src->length; + dup->negative = src->negative; + dup->type = src->type; + + if (!src->isDynamic) { + /* Copy over data from/to fixed buffer. */ + XMEMCPY(dup->intData, src->intData, WOLFSSL_ASN1_INTEGER_MAX); + } + else if (wolfssl_asn1_integer_require_len(dup, src->length, 0) == 0) { + wolfSSL_ASN1_INTEGER_free(dup); + dup = NULL; + } + else { + XMEMCPY(dup->data, src->data, src->length); + } + } + + return dup; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + +#if defined(OPENSSL_EXTRA) + +/* Compare values in two ASN.1 INTEGER objects. + * + * @param [in] a First ASN.1 INTEGER object. + * @param [in] b Second ASN.1 INTEGER object. + * @return Negative value when a is less than b. + * @return 0 when a equals b. + * @return Positive value when a is greater than b. + * @return -1 when a or b is NULL. + */ +int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, + const WOLFSSL_ASN1_INTEGER* b) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_cmp"); + + /* Validate parameters. */ + if ((a == NULL) || (b == NULL)) { + WOLFSSL_MSG("Bad parameter."); + ret = -1; + } + /* Negative value < Positive value */ + else if (a->negative && !b->negative) { + ret = -1; + } + /* Positive value > Negative value */ + else if (!a->negative && b->negative) { + ret = 1; + } + else { + /* Check for difference in length. */ + if (a->length != b->length) { + ret = a->length - b->length; + } + else { + /* Compare data given they are the same length. */ + ret = XMEMCMP(a->data, b->data, a->length); + } + /* Reverse comparison result when both negative. */ + if (a->negative) { + ret = -ret; + } + } + + WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_cmp", ret); + + return ret; +} + + +/* Calculate 2's complement of DER encoding. + * + * @param [in] data Array that is number. + * @param [in] length Number of bytes in array. + * @return 0 on success. + * @return -1 when get length from DER header failed. + */ +static void wolfssl_twos_compl(byte* data, int length) +{ + int i; + + /* Invert bits - 1's complement. */ + for (i = 0; i < length; ++i) { + data[i] = ~data[i]; + } + /* 2's complement - add 1. */ + for (i = length - 1; (++data[i]) == 0; --i) { + /* Do nothing. */ + } +} + +/* Calculate 2's complement of DER encoding. + * + * @param [in] data Array that is number. + * @param [in] length Number of bytes in array. + * @param [out] neg When NULL, 2's complement data. + * When not NULL, check for negative first and return. + * @return 0 on success. + * @return -1 when get length from DER header failed. + */ +static int wolfssl_asn1_int_twos_compl(byte* data, int length, byte* neg) +{ + int ret = 0; + word32 idx = 1; /* Skip tag. */ + int len; + + /* Get length from DER header. */ + if (GetLength(data, &idx, &len, length) < 0) { + ret = -1; + } + else { + if (neg != NULL) { + *neg = data[idx] & 0x80; + } + if ((neg == NULL) || (*neg != 0)) { + wolfssl_twos_compl(data + idx, length - idx); + } + } + + return ret; +} + +/* Encode ASN.1 INTEGER as DER without tag. + * + * When out points to NULL, a new buffer is allocated and returned. + * + * @param [in] a ASN.1 INTEGER object. + * @param [in, out] out Pointer to buffer to hold encoding. May point to NULL. + * @return Length of encoding on success. + * @return -1 when a is NULL or no data, out is NULL, dynamic memory allocation + * fails or encoding length fails. + */ +int wolfSSL_i2d_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER* a, unsigned char** out) +{ + int ret = 0; + byte* buf = NULL; + + WOLFSSL_ENTER("wolfSSL_i2d_ASN1_INTEGER"); + + /* Validate parameters. */ + if ((a == NULL) || (a->data == NULL) || (a->length <= 0) || (out == NULL)) { + WOLFSSL_MSG("Bad parameter."); + ret = -1; + } + + if ((ret == 0) && (*out == NULL)) { + /* Allocate buffer to hold encoding. */ + buf = (unsigned char*)XMALLOC(a->length, NULL, DYNAMIC_TYPE_ASN1); + if (buf == NULL) { + WOLFSSL_MSG("Failed to allocate output buffer."); + ret = -1; + } + /* Return any allocated buffer. */ + *out = buf; + } + if (ret == 0) { + /* Copy the data (including tag and length) into output buffer. */ + XMEMCPY(*out, a->data, a->length); + /* Only magnitude of the number stored (i.e. the sign isn't encoded). + * The "negative" field is 1 if the value must be interpreted as + * negative and we need to output the 2's complement of the value in + * the DER output. + */ + if (a->negative) { + ret = wolfssl_asn1_int_twos_compl(*out, a->length, NULL); + } + } + if (ret == 0) { + ret = a->length; + /* Move pointer on passed encoding when buffer passed in. */ + if (buf == NULL) { + *out += a->length; + } + } + /* Dispose of any dynamically allocated data on error. */ + else if (buf != NULL) { + /* Dispose of buffer allocated locally on error. */ + XFREE(buf, NULL, DYNAMIC_TYPE_ASN1); + /* Don't return freed buffer. */ + *out = NULL; + } + + WOLFSSL_LEAVE("wolfSSL_i2d_ASN1_INTEGER", ret); + + return ret; +} + +/* Decode DER encoding of ASN.1 INTEGER. + * + * @param [out] a ASN.1 INTEGER object. May be NULL. + * @param [in, out] in Pointer to buffer containing DER encoding. + * @param [in] inSz Length of data in buffer. + * @return ASN.1 INTEGER object on success. + * @return NULL when in or *in is NULL, inSz is less than or equal to 2 or + * parsing DER failed. + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_d2i_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER** a, + const unsigned char** in, long inSz) +{ + WOLFSSL_ASN1_INTEGER* ret = NULL; + int err = 0; + word32 idx = 1; + int len = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_ASN1_INTEGER"); + + /* Validate parameters. */ + if ((in == NULL) || (*in == NULL) || (inSz <= 2)) { + WOLFSSL_MSG("Bad parameter"); + err = 1; + } + + /* Check that the tag is correct. */ + if ((!err) && (*in)[0] != ASN_INTEGER) { + WOLFSSL_MSG("Tag doesn't indicate integer type."); + err = 1; + } + /* Check that length and use this instead of inSz. */ + if ((!err) && (GetLength(*in, &idx, &len, (word32)inSz) <= 0)) { + WOLFSSL_MSG("ASN.1 length not valid."); + err = 1; + } + /* Allocate a new ASN.1 INTEGER object. */ + if ((!err) && ((ret = wolfSSL_ASN1_INTEGER_new()) == NULL)) { + err = 1; + } + if ((!err) && (wolfssl_asn1_integer_require_len(ret, idx + len, 0) != 1)) { + err = 1; + } + if (!err) { + /* Set type. */ + ret->type = V_ASN1_INTEGER; + + /* Copy DER encoding and length. */ + XMEMCPY(ret->data, *in, idx + len); + ret->length = idx + len; + /* Do 2's complement if number is negative. */ + if (wolfssl_asn1_int_twos_compl(ret->data, ret->length, &ret->negative) + != 0) { + err = 1; + } + } + if ((!err) && ret->negative) { + /* Update type if number was negative. */ + ret->type |= V_ASN1_NEG_INTEGER; + } + + if (err) { + /* Dispose of dynamically allocated data on error. */ + wolfSSL_ASN1_INTEGER_free(ret); + ret = NULL; + } + else { + if (a != NULL) { + /* Return ASN.1 INTEGER through a. */ + *a = ret; + } + *in += ret->length; + } + + return ret; +} + +#ifndef NO_BIO + +/* Get length of leading hexadecimal characters. + * + * Looks for continuation character before carriage returns and line feeds. + * + * @param [in] str String with input. + * @param [in] len Length of string. + * @param [out] cont Line continuation character at end of line before + * carriage returns and line feeds. + * @return Number of leading hexadecimal characters in string. + */ +static int wolfssl_a2i_asn1_integer_clear_to_eol(char* str, int len, int* cont) +{ + byte num; + word32 nLen; + int i; + + /* Strip off trailing carriage returns and line feeds. */ + while ((len > 0) && ((str[len - 1] == '\n') || (str[len - 1] == '\r'))) { + len--; + } + /* Check for line continuation character. */ + if ((len > 0) && (str[len - 1] == '\\')) { + *cont = 1; + len--; + } + else { + *cont = 0; + } + + /* Find end of hexadecimal characters. */ + nLen = 1; + for (i = 0; i < len; i++) { + /* Check if character is a hexadecimal character. */ + if (Base16_Decode((const byte*)str + i, 1, &num, &nLen) == ASN_INPUT_E) + { + /* Found end of hexadecimal characters, return count. */ + len = i; + break; + } + } + + return len; +} + +/* Read number from BIO as a string. + * + * Line continuation character at end of line means next line must be read. + * + * @param [in] bio BIO to read from. + * @param [in] asn1 ASN.1 INTEGER object to put number into. + * @param [in, out] buf Buffer to use when reading. + * @param [in] size Length of buffer in bytes. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_a2i_ASN1_INTEGER(WOLFSSL_BIO *bio, WOLFSSL_ASN1_INTEGER *asn1, + char *buf, int size) +{ + int ret = 1; + int readNextLine = 1; + int lineLen; + int len; + word32 outLen = 0; + const int hdrSz = 1 + MAX_LENGTH_SZ; + + WOLFSSL_ENTER("wolfSSL_a2i_ASN1_INTEGER"); + + if ((bio == NULL) || (asn1 == NULL) || (buf == NULL) || (size <= 0)) { + WOLFSSL_MSG("Bad parameter"); + ret = 0; + } + + while ((ret == 1) && readNextLine) { + /* Assume we won't be reading any more. */ + readNextLine = 0; + + /* Read a line. */ + lineLen = wolfSSL_BIO_gets(bio, buf, size); + if (lineLen <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_gets error"); + ret = 0; + } + + if (ret == 1) { + /* Find length of hexadecimal digits in string. */ + lineLen = wolfssl_a2i_asn1_integer_clear_to_eol(buf, lineLen, + &readNextLine); + /* Check we have a valid hexadecimal string to process. */ + if ((lineLen == 0) || ((lineLen % 2) != 0)) { + WOLFSSL_MSG("Invalid line length"); + ret = 0; + } + } + if (ret == 1) { + /* Calculate length of complete number so far. */ + len = asn1->length + (lineLen / 2); + /* Make sure enough space for number and maximum header. */ + if (wolfssl_asn1_integer_require_len(asn1, len + hdrSz, outLen != 0) + != 1) { + ret = 0; + } + } + if (ret == 1) { + /* Decode string and append to data. */ + outLen = (word32)(lineLen / 2); + (void)Base16_Decode((byte*)buf, lineLen, asn1->data + asn1->length, + &outLen); + } + if (ret == 1) { + /* Update length of data. */ + asn1->length += outLen; + } + } + + if (ret == 1) { + int idx; + + /* Get ASN.1 header length. */ + idx = SetASNInt(asn1->length, asn1->data[0], NULL); + /* Move data to be after ASN.1 header. */ + XMEMMOVE(asn1->data + idx, asn1->data, asn1->length); + /* Encode ASN.1 header. */ + SetASNInt(asn1->length, asn1->data[idx], asn1->data); + /* Update length of data. */ + asn1->length += idx; + } + + return ret; +} + +/* Write out number in ASN.1 INTEGER object to BIO as string. + * + * @param [in] bp BIO to write to. + * @param [in] a ASN.1 INTEGER object. + * @return Number of characters written on success. + * @return 0 when bp or a is NULL. + * @return 0 DER header in data is invalid. + */ +int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) +{ + int err = 0; + word32 idx = 1; /* Skip ASN.1 INTEGER tag byte. */ + int len = 0; + byte buf[WOLFSSL_ASN1_INTEGER_MAX * 2 + 1]; + word32 bufLen; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); + + /* Validate parameters. */ + if ((bp == NULL) || (a == NULL)) { + err = 1; + } + + if (!err) { + /* Read DER length - must be at least 1 byte. */ + if (GetLength(a->data, &idx, &len, a->length) <= 0) { + err = 1; + } + } + + /* Keep encoding and writing while no error and bytes in data. */ + while ((!err) && (idx < (word32)a->length)) { + /* Number of bytes left to encode. */ + int encLen = a->length - idx; + /* Reduce to maximum buffer size if necessary. */ + if (encLen > (int)sizeof(buf) / 2) { + encLen = (int)sizeof(buf) / 2; + } + + /* Encode bytes from data into buffer. */ + bufLen = (int)sizeof(buf); + (void)Base16_Encode(a->data + idx, encLen, buf, &bufLen); + /* Update index to next bytes to encoded. */ + idx += encLen; + + /* Write out characters but not NUL char. */ + if (wolfSSL_BIO_write(bp, buf, bufLen - 1) != (int)(bufLen - 1)) { + err = 1; + } + } + + if (err) { + /* Return 0 on error. */ + len = 0; + } + /* Return total number of characters written. */ + return len * 2; +} +#endif /* !NO_BIO */ + +#ifndef NO_ASN +/* Determine if a pad byte is required and its value for a number. + * + * Assumes values pointed to by pad and padVal are both 0. + * + * @param [in] data Number encoded as big-endian bytes. + * @param [in] len Length of number in bytes. + * @param [in, out] neg Indicates number is negative. + * @param [out] pad Number of padding bytes required. + * @param [out] padVal Padding byte to preprend. + */ +static void wolfssl_asn1_integer_pad(unsigned char* data, int len, + unsigned char* neg, char* pad, unsigned char* padVal) +{ + /* Check for empty data. */ + if (len == 0) { + *pad = 1; + *padVal = 0x00; + *neg = 0; + } + else { + /* Get first, most significant, byte of encoded number. */ + unsigned char firstByte = data[0]; + + /* 0 can't be negative. */ + if ((len == 1) && (firstByte == 0x00)) { + *neg = 0; + } + /* Positive value must not have top bit of first byte set. */ + if ((!*neg) && (firstByte >= 0x80)) { + *pad = 1; + *padVal = 0x00; + } + /* Negative numbers are two's complemented. + * Two's complement value must have top bit set. + */ + else if (*neg && (firstByte > 0x80)) { + *pad = 1; + *padVal = 0xff; + } + /* Checking for: 0x80[00]* + * when negative that when two's complemented will be: 0x80[00]* + * and therefore doesn't require pad byte. + */ + else if (*neg && (firstByte == 0x80)) { + int i; + /* Check rest of bytes. */ + for (i = 1; i < len; i++) { + if (data[i] != 0x00) { + /* Not 0x80[00]* */ + *pad = 1; + *padVal = 0xff; + break; + } + } + } + } +} + +/* Convert ASN.1 INTEGER object into content octets. + * + * TODO: compatibility with OpenSSL? OpenSSL assumes data not DER encoded. + * + * When pp points to a buffer, on success pp will point to after the encoded + * data. + * + * @param [in] a ASN.1 INTEGER object. + * @param [in, out] pp Pointer to buffer. May be NULL. Cannot point to NULL. + * @return Length of encoding on success. + * @return 0 when a is NULL, pp points to NULL or DER length encoding invalid. + */ +int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp) +{ + int err = 0; + int len = 0; + char pad = 0; + unsigned char padVal = 0; + word32 idx = 1; + + WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER"); + + /* Validate parameters. */ + if ((a == NULL) || ((pp != NULL) && (*pp == NULL))) { + err = 1; + } + + /* Get length from DER encoding. */ + if ((!err) && (GetLength_ex(a->data, &idx, &len, a->dataMax, 0) < 0)) { + err = 1; + } + + if (!err) { + /* Determine pad length and value. */ + wolfssl_asn1_integer_pad(a->data + idx, len, &a->negative, &pad, + &padVal); + /* Total encoded length is number length plus one when padding. */ + len += (int)pad; + } + + /* Check buffer supplied to write into. */ + if ((!err) && (pp != NULL)) { + /* Put in any pad byte. */ + if (pad) { + (*pp)[0] = padVal; + } + /* Copy remaining bytes into output buffer. */ + XMEMCPY(*pp + pad, a->data + idx, len - pad); + /* Two's complement copied bytes when negative. */ + if (a->negative) { + wolfssl_twos_compl(*pp + pad, len - pad); + } + /* Move pointer past encoded data. */ + *pp += len; + } + + return len; +} + +/* Make a big number with the value in the ASN.1 INTEGER object. + * + * A new big number object is allocated when bn is NULL. + * + * @param [in] ai ASN.1 INTEGER object. + * @param [in] bn Big number object. May be NULL. + * @return Big number object on success. + * @return NULL when ai is NULL or converting from binary fails. + */ +WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn) +{ + int err = 0; + word32 idx = 1; + int len = 0; + WOLFSSL_BIGNUM* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN"); + + /* Validate parameters. */ + if (ai == NULL) { + err = 1; + } + + if (!err) { + /* Get the length of ASN.1 INTEGER number. */ + if ((ai->data[0] != ASN_INTEGER) || (GetLength(ai->data, &idx, &len, + ai->length) <= 0)) { + #if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) + idx = 0; + len = ai->length; + #else + WOLFSSL_MSG("Data in WOLFSSL_ASN1_INTEGER not DER encoded"); + err = 1; + #endif + } + } + if (!err) { + /* Convert binary to big number. */ + ret = wolfSSL_BN_bin2bn(ai->data + idx, len, bn); + if (ret != NULL) { + /* Handle negative. */ + (void)wolfssl_bn_set_neg(ret, ai->negative); + } + } + + return ret; +} +#endif /* !NO_ASN */ + +/* Create an ASN.1 INTEGER object from big number. + * + * Allocates a new ASN.1 INTEGER object when ai is NULL. + * + * @param [in] bn Big number to encode. + * @param [in] ai ASN.1 INTEGER object. May be NULL. + * @return ASN.1 INTEGER object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_BN_to_ASN1_INTEGER(const WOLFSSL_BIGNUM *bn, + WOLFSSL_ASN1_INTEGER *ai) +{ + int err = 0; + WOLFSSL_ASN1_INTEGER* a = NULL; + int len = 0; + int numBits = 0; + byte firstByte = 0; + + WOLFSSL_ENTER("wolfSSL_BN_to_ASN1_INTEGER"); + + /* Validate parameters. */ + if (bn == NULL) { + err = 1; + } + /* Use ASN.1 INTEGER object if provided. */ + else if (ai != NULL) { + a = ai; + } + /* Create an ASN.1 INTEGER object to return. */ + else { + a = wolfSSL_ASN1_INTEGER_new(); + if (a == NULL) { + err = 1; + } + } + + /* Check we have an ASN.1 INTEGER object to set. */ + if (!err) { + int length; + + /* Set type and negative. */ + a->type = V_ASN1_INTEGER; + if (wolfSSL_BN_is_negative(bn) && !wolfSSL_BN_is_zero(bn)) { + a->negative = 1; + a->type |= V_ASN1_NEG_INTEGER; + } + + /* Get length in bytes of encoded number. */ + len = wolfSSL_BN_num_bytes(bn); + if (len == 0) { + len = 1; + } + /* Get length in bits of encoded number. */ + numBits = wolfSSL_BN_num_bits(bn); + /* Leading zero required if most-significant byte has top bit set. */ + if ((numBits % 8) == 7) { + firstByte = 0x80; + } + /* Get length of header based on length of number. */ + length = SetASNInt(len, firstByte, NULL); + if (firstByte != 0) { + /* Add one for leading zero. */ + length++; + } + /* Add number of bytes to encode number. */ + length += len; + + /* Update data field to handle length. */ + if (wolfssl_asn1_integer_require_len(a, length, 0) != 1) { + err = 1; + } + } + if (!err) { + /* Write ASN.1 header. */ + int idx = SetASNInt(len, firstByte, a->data); + + /* Populate data. */ + if (numBits == 0) { + a->data[idx] = 0; + } + else { + if (firstByte != 0) { + a->data[idx++] = 0; + } + /* Add encoded number. */ + len = wolfSSL_BN_bn2bin(bn, a->data + idx); + if (len < 0) { + err = 1; + } + } + + /* Set length to encoded length. */ + a->length = idx + len; + } + + if (err) { + /* Can't use ASN.1 INTEGER object. */ + if (a != ai) { + wolfSSL_ASN1_INTEGER_free(a); + } + a = NULL; + } + return a; +} + +/* Get the value of the ASN.1 INTEGER as a long. + * + * Returning 0 on NULL and -1 on error is consistent with OpenSSL. + * + * @param [in] a ASN.1 INTEGER object. + * @return Value as a long. + * @return 0 when a is NULL. + * @return -1 when a big number operation fails. + */ +long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* a) +{ + long ret = 1; + WOLFSSL_BIGNUM* bn = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_get"); + + /* Validate parameter. */ + if (a == NULL) { + ret = 0; + } + + if (ret > 0) { + /* Create a big number from the DER encoding. */ + bn = wolfSSL_ASN1_INTEGER_to_BN(a, NULL); + if (bn == NULL) { + ret = -1; + } + } + if (ret > 0) { + /* Get the big number as a word. */ + ret = wolfSSL_BN_get_word(bn); + /* Negate number of ASN.1 INTEGER was negative. */ + if (a->negative == 1) { + ret = -ret; + } + } + + /* Dispose of big number as no longer needed. */ + if (bn != NULL) { + wolfSSL_BN_free(bn); + } + + WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_get", (int)ret); + + return ret; +} + + +/* Sets the value of the ASN.1 INTEGER object to the long value. + * + * @param [in, out] a ASN.1 INTEGER object. + * @param [in] v Value to set. + * @return 1 on success. + * @return 0 when a is NULL. + */ +int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v) +{ + int ret = 1; + byte j; + unsigned int i = 0; + byte tmp[sizeof(long)]; + byte pad = 0; + + /* Validate parameters. */ + if (a == NULL) { + ret = 0; + } + if (ret == 1) { + wolfssl_asn1_integer_reset_data(a); + + /* Check for negative. */ + if (v < 0) { + /* Set negative and 2's complement the value. */ + a->negative = 1; + a->type |= V_ASN1_NEG; + v = -v; + } + + /* Put value into temporary buffer - at least one byte encoded. */ + tmp[0] = (byte)(v & 0xff); + v >>= 8; + for (j = 1; j < (byte)sizeof(long); j++) { + if (v == 0) { + break; + } + tmp[j] = (byte)(v & 0xff); + v >>= 8; + } + /* Pad with 0x00 to indicate positive number when top bit set. */ + if ((!a->negative) && (tmp[j-1] & 0x80)) { + pad = 1; + } + + /* Set tag. */ + a->data[i++] = ASN_INTEGER; + /* Set length of encoded value. */ + a->data[i++] = pad + j; + /* Set length of DER encoding. +2 for tag and length */ + a->length = 2 + pad + j; + + /* Add pad byte if required. */ + if (pad == 1) { + a->data[i++] = 0; + } + /* Copy in data. */ + for (; j > 0; j--) { + a->data[i++] = tmp[j-1]; + } + } + + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +/******************************************************************************* + * ASN1_OBJECT APIs + ******************************************************************************/ + +#if !defined(NO_ASN) +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Create a new ASN.1 OBJECT_ID object. + * + * @return ASN.1 OBJECT_ID object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) +{ + WOLFSSL_ASN1_OBJECT* obj; + + /* Allocate memory for new ASN.1 OBJECT. */ + obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL, + DYNAMIC_TYPE_ASN1); + if (obj != NULL) { + XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT)); + /* Setup pointers. */ + obj->d.ia5 = &(obj->d.ia5_internal); + #if defined(OPENSSL_ALL) + obj->d.iPAddress = &(obj->d.iPAddress_internal); + #endif + /* Object was allocated. */ + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + } + + return obj; +} + +/* Dispose of any ASN.1 OBJECT_ID dynamically allocated data. + * + * Do not use obj after calling this function. + * + * @param [in, out] obj ASN.1 OBJECT_ID object. + */ +void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) +{ + if (obj != NULL) { + /* Check for dynamically allocated copy of encoded data. */ + if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) { + #ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_MSG("Freeing ASN1 data"); + #endif + XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1); + obj->obj = NULL; + } + #if defined(OPENSSL_EXTRA) + /* Check for path length ASN.1 INTEGER - X.509 extension. */ + if (obj->pathlen != NULL) { + wolfSSL_ASN1_INTEGER_free(obj->pathlen); + obj->pathlen = NULL; + } + #endif + /* Check whether object was dynamically allocated. */ + if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) { + #ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_MSG("Freeing ASN1 OBJECT"); + #endif + XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); + } + } +} + +/* Duplicate the ASN.1 OBJECT_ID object. + * + * @param [in] obj ASN.1 OBJECT_ID object to copy. + * @return New ASN.1 OBJECT_ID object on success. + * @return NULL when obj is NULL or dynamic memory allocation fails. + */ +WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_dup(WOLFSSL_ASN1_OBJECT* obj) +{ + WOLFSSL_ASN1_OBJECT* dupl = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_OBJECT_dup"); + + /* Validate parameter. */ + if (obj == NULL) { + WOLFSSL_MSG("Bad parameter"); + } + /* Create a new ASN.1 OBJECT_ID object to return. */ + else if ((dupl = wolfSSL_ASN1_OBJECT_new()) == NULL) { + WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new error"); + } + if (dupl != NULL) { + /* Copy short name. */ + XMEMCPY(dupl->sName, obj->sName, WOLFSSL_MAX_SNAME); + /* Copy simple fields. */ + dupl->type = obj->type; + dupl->grp = obj->grp; + dupl->nid = obj->nid; + dupl->objSz = obj->objSz; + /* Check for encoding. */ + if (obj->obj) { + /* Allocate memory for ASN.1 OBJECT_ID DER encoding. */ + dupl->obj = (const unsigned char*)XMALLOC(obj->objSz, NULL, + DYNAMIC_TYPE_ASN1); + if (dupl->obj == NULL) { + WOLFSSL_MSG("ASN1 obj malloc error"); + wolfSSL_ASN1_OBJECT_free(dupl); + dupl = NULL; + } + else { + /* Encoding buffer was dynamically allocated. */ + dupl->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; + /* Copy DER encoding. */ + XMEMCPY((byte*)dupl->obj, obj->obj, obj->objSz); + } + } + } + + return dupl; +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#endif /* !NO_ASN */ + +#ifdef OPENSSL_EXTRA + +/** + * Parse DER encoding and return header information. + * + * *in is moved to the value of the ASN1 object + * + * @param [in, out] in Pointer to BER encoded data. + * @param [out] len Length of parsed ASN1 object + * @param [out] tag Tag value of parsed ASN1 object + * @param [out] cls Class of parsed ASN1 object + * @param [in] inLen Length of *in buffer + * @return int Depends on which bits are set in the returned int: + * 0x80 an error occurred during parsing. + * 0x20 parsed object is constructed. + * 0x01 the parsed object length is indefinite. + */ +int wolfSSL_ASN1_get_object(const unsigned char **in, long *len, int *tag, + int *cls, long inLen) +{ + int err = 0; + word32 inOutIdx = 0; + int l = 0; + byte t = 0; + int ret = 0x80; + + WOLFSSL_ENTER("wolfSSL_ASN1_get_object"); + + if ((in == NULL) || (*in == NULL) || (len == NULL) || (tag == NULL) || + (cls == NULL) || (inLen <= 0)) { + WOLFSSL_MSG("Bad parameter"); + err = 1; + } + if (!err) { + /* Length at least 1, parameters valid - cannot fail to get tag. */ + GetASNTag(*in, &inOutIdx, &t, (word32)inLen); + /* Get length in DER encoding. */ + if (GetLength_ex(*in, &inOutIdx, &l, (word32)inLen, 0) < 0) { + WOLFSSL_MSG("GetLength error"); + err = 1; + } + } + if (!err) { + /* Return header information. */ + *tag = t & ASN_TYPE_MASK; /* Tag number is 5 lsb */ + *cls = t & ASN_CLASS_MASK; /* Class is 2 msb */ + *len = l; + ret = t & ASN_CONSTRUCTED; + + if (l > (int)(inLen - inOutIdx)) { + /* Still return other values but indicate error in msb */ + ret |= 0x80; + } + + /* Move pointer to after DER header. */ + *in += inOutIdx; + } + + return ret; +} + +/* Creates and ASN.1 OBJECT_ID object from DER encoding. + * + * @param [out] a Pointer to return new ASN.1 OBJECT_ID through. + * @param [in, out] der Pointer to buffer holding DER encoding. + * @param [in] length Length of DER encoding in bytes. + * @return New ASN.1 OBJECT_ID object on success. + * @return NULL when der or *der is NULL or length is less than or equal zero. + * @return NULL when not an OBJECT_ID or decoding fails. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_OBJECT *wolfSSL_d2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a, + const unsigned char **der, long length) +{ + WOLFSSL_ASN1_OBJECT* ret = NULL; + int err = 0; + const unsigned char *d; + long len = 0; + int tag = 0; + int cls; + + WOLFSSL_ENTER("wolfSSL_d2i_ASN1_OBJECT"); + + /* Validate parameters. */ + if ((der == NULL) || (*der == NULL) || (length <= 0)) { + WOLFSSL_MSG("Bad parameter"); + err = 1; + } + if (!err) { + /* Get pointer to be modified along the way. */ + d = *der; + + /* Move d to value and get length and tag. */ + if (wolfSSL_ASN1_get_object(&d, &len, &tag, &cls, length) & 0x80) { + WOLFSSL_MSG("wolfSSL_ASN1_get_object error"); + err = 1; + } + } + /* Check it DER encoding is of an OBJECT_ID. */ + if ((!err) && (tag != ASN_OBJECT_ID)) { + WOLFSSL_MSG("Not an ASN object"); + err = 1; + } + /* Create an ASN.1 OBJECT_ID_object from value. TODO: not DER encoding? */ + if ((!err) && ((ret = wolfSSL_c2i_ASN1_OBJECT(a, &d, len)) != NULL)) { + /* Update pointer to after decoded bytes. */ + *der = d; + } + + return ret; +} + +/* Write out DER encoding of ASN.1 OBJECT_ID. + * + * When pp is NULL, length is returned. + * When pp points to NULL, a new buffer is allocated and returned through pp. + * When pp points to a buffer, it is moved on past encoded data on success. + * + * @param [in] a ASN.1 OBJECT_ID object. + * @param [in, out] pp Pointer to buffer to write to. May be NULL. + * @return Length of encoding on success. + * @return 0 when a or encoding buffer is NULL. + * @return 0 when dynamic memory allocation fails. + */ +int wolfSSL_i2d_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT *a, unsigned char **pp) +{ + int len = 0; + + WOLFSSL_ENTER("wolfSSL_i2d_ASN1_OBJECT"); + + /* Validate parameters */ + if ((a == NULL) || (a->obj == NULL)) { + WOLFSSL_MSG("Bad parameters"); + } + /* Only return length when no pointer supplied. */ + else if (pp == NULL) { + len = (int)a->objSz; + } + else { + byte *p = NULL; + + /* Check if we have a buffer to encode into. */ + if (*pp == NULL) { + /* Allocate a new buffer to return. */ + p = (byte*)XMALLOC(a->objSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (p == NULL) { + WOLFSSL_MSG("Bad malloc"); + } + else { + /* Return allocated buffer. */ + *pp = p; + } + } + + /* Check we have a buffer to encode into. */ + if (*pp != NULL) { + /* Copy in DER encoding. */ + XMEMCPY(*pp, a->obj, a->objSz); + /* Move on pointer if user supplied. */ + if (p == NULL) { + *pp += a->objSz; + } + /* Return length of DER encoding. */ + len = a->objSz; + } + } + + return len; +} + +/* Create an ASN.1 OBJECT_ID object from the content octets. + * + * @param [out] a Pointer to return ASN.1 OBJECT_ID object. + * @param [in, out] pp Pointer to buffer holding content octets. + * @param [in] len Length of content octets in bytes. + * @return New ASN.1 OBJECT_ID object on success. + * @return NULL when pp or *pp is NULL or length is less than or equal zero. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_OBJECT *wolfSSL_c2i_ASN1_OBJECT(WOLFSSL_ASN1_OBJECT **a, + const unsigned char **pp, long len) +{ + int err = 0; + WOLFSSL_ASN1_OBJECT* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_c2i_ASN1_OBJECT"); + + /* Validate parameters. */ + if ((pp == NULL) || (*pp == NULL) || (len <= 0)) { + WOLFSSL_MSG("Bad parameter"); + err = 1; + } + + /* Create a new ASN.1 OBJECT_ID object. */ + if ((!err) && ((ret = wolfSSL_ASN1_OBJECT_new()) == NULL)) { + WOLFSSL_MSG("wolfSSL_ASN1_OBJECT_new error"); + err = 1; + } + + if (!err) { + /* Allocate memory for content octets. */ + ret->obj = (const unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1); + if (ret->obj == NULL) { + WOLFSSL_MSG("error allocating asn data memory"); + wolfSSL_ASN1_OBJECT_free(ret); + ret = NULL; + err = 1; + } + } + + if (!err) { + /* Content octets buffer was dynamically allocated. */ + ret->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; + /* Copy in content octets and set size. */ + XMEMCPY((byte*)ret->obj, *pp, len); + ret->objSz = (unsigned int)len; + + /* Move pointer to after data copied out. */ + *pp += len; + /* Return ASN.1 OBJECT_ID object through a if required. */ + if (a != NULL) { + *a = ret; + } + } + + return ret; +} + +/* Write at most buf_len bytes of textual representation of ASN.1 OBJECT_ID. + * + * @param [in, out] buf Buffer to write to. + * @param [in] buf_len Length of buffer in bytes. + * @param [in] a ASN.1 OBJECT_ID object. + * @return Number of bytes written on success. + * @return 0 on failure. + */ +int wolfSSL_i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) +{ + WOLFSSL_ENTER("wolfSSL_i2t_ASN1_OBJECT"); + + return wolfSSL_OBJ_obj2txt(buf, buf_len, a, 0); +} + +#ifndef NO_BIO +/* Write out the text encoding of the ASN.1 OBJECT_ID. + * + * @param [in] bp BIO to write to. + * @param [in] a ASN.1 OBJECT_ID object. + * @return Number of bytes written on success. + * @return 0 on failure. + */ +int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, WOLFSSL_ASN1_OBJECT *a) +{ + int done = 0; + int length = 0; + int cLen = 0; + word32 idx = 0; + const char null_str[] = "NULL"; + const char invalid_str[] = ""; + char buf[80]; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_OBJECT"); + + /* Validate parameters. */ + if (bp == NULL) { + done = 1; + } + + /* NULL object is written as "NULL". */ + if ((!done) && (a == NULL)) { + /* Write "NULL" - as done in OpenSSL. */ + length = wolfSSL_BIO_write(bp, null_str, (int)XSTRLEN(null_str)); + done = 1; + } + + /* Try getting text version and write it out. */ + if ((!done) && ((length = i2t_ASN1_OBJECT(buf, sizeof(buf), a)) > 0)) { + length = wolfSSL_BIO_write(bp, buf, length); + done = 1; + } + + /* Look for DER header. */ + if ((!done) && ((a->obj == NULL) || (a->obj[idx++] != ASN_OBJECT_ID))) { + WOLFSSL_MSG("Bad ASN1 Object"); + done = 1; + } + + /* Get length from DER header. */ + if ((!done) && (GetLength((const byte*)a->obj, &idx, &cLen, a->objSz) < 0)) + { + length = 0; + done = 1; + } + + if (!done) { + /* Write out "" and dump content. */ + length = wolfSSL_BIO_write(bp, invalid_str, (int)XSTRLEN(invalid_str)); + length += wolfSSL_BIO_dump(bp, (const char*)(a->obj + idx), cLen); + } + + return length; +} +#endif /* !NO_BIO */ + +#endif /* OPENSSL_EXTRA */ + +/******************************************************************************* + * ASN1_SK_OBJECT APIs + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) +/* Create a new WOLFSSL_ASN1_OBJECT stack. + * + * @return New WOLFSSL_ASN1_OBJECT stack on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void) +{ + WOLFSSL_ENTER("wolfSSL_sk_new_asn1_obj"); + + return wolfssl_sk_new_type(STACK_TYPE_OBJ); +} + +/* Dispose of WOLFSL_ASN1_OBJECT stack. + * + * @param [in, out] sk Stack to free nodes in. + */ +void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + /* Dispose of stack. */ + wolfSSL_sk_free(sk); +} + +/* Dispose of all ASN.1 OBJECT_ID objects in ASN1_OBJECT stack. + * + * This is different then wolfSSL_ASN1_OBJECT_free in that it allows for + * choosing the function to use when freeing an ASN1_OBJECT stack. + * + * @param [in, out] sk ASN.1 OBJECT_ID stack to free. + * @param [in] f Free function to apply to each ASN.1 OBJECT_ID object. + */ +void wolfSSL_sk_ASN1_OBJECT_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + void (*f) (WOLFSSL_ASN1_OBJECT*)) +{ + WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_pop_free"); + wolfSSL_sk_pop_free(sk, (wolfSSL_sk_freefunc)f); +} + +/* Push a WOLFSSL_ASN1_OBJECT onto stack. + * + * @param [in, out] sk ASN.1 OBJECT_ID stack. + * @param [in] obj ASN.1 OBJECT_ID object to push on. Cannot be NULL. + * @return 1 on success. + * @return 0 when sk or obj is NULL. + * @return 0 when dynamic memory allocation fails. + */ +int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + WOLFSSL_ASN1_OBJECT* obj) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push"); + + /* Push on when we have a stack and object to work with. */ + if ((sk != NULL) && (obj != NULL)) { + ret = wolfSSL_sk_push(sk, obj); + } + + return ret; +} + +/* Pop off a WOLFSSL_ASN1_OBJECT from the stack. + * + * @param [in, out] sk ASN.1 OBJECT_ID stack. + * @return ASN.1 OBJECT_ID object on success. + * @return NULL when stack is NULL or no nodes left in stack. + */ +WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + return (WOLFSSL_ASN1_OBJECT*)wolfssl_sk_pop_type(sk, STACK_TYPE_OBJ); +} + +#endif /* OPENSSL_EXTRA && !NO_ASN */ + +/******************************************************************************* + * ASN1_STRING APIs + ******************************************************************************/ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + +/* Create a new ASN.1 STRING object. + * + * @return New ASN.1 STRING object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void) +{ + WOLFSSL_ASN1_STRING* asn1; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new"); +#endif + + asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL, + DYNAMIC_TYPE_OPENSSL); + if (asn1 != NULL) { + XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING)); + } + + return asn1; +} + +/* Create a new ASN.1 STRING object. + * + * @param [in] type Encoding type. + * @return New ASN.1 STRING object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type) +{ + WOLFSSL_ASN1_STRING* asn1; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new"); +#endif + + asn1 = wolfSSL_ASN1_STRING_new(); + if (asn1 != NULL) { + asn1->type = type; + } + + return asn1; +} + +/* Dispose of ASN.1 STRING object. + * + * @param [in, out] asn1 ASN.1 STRING object. + */ +void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1) +{ +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free"); +#endif + + /* Check we have an object to free. */ + if (asn1 != NULL) { + /* Dispose of dynamic data. */ + if ((asn1->length > 0) && asn1->isDynamic) { + XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + } + /* Dispose of ASN.1 STRING object. */ + XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL); +} + +/* Copy an ASN.1 STRING object from src into dest. + * + * @param [in, out] dest ASN.1 STRING object to copy into. + * @param [in] src ASN.1 STRING object to copy from. + */ +int wolfSSL_ASN1_STRING_copy(WOLFSSL_ASN1_STRING* dest, + const WOLFSSL_ASN1_STRING* src) +{ + int ret = 1; + + /* Validate parameters. */ + if ((src == NULL) || (dest == NULL)) { + ret = 0; + } + /* Set the DER encoding. */ + if ((ret == 1) && (wolfSSL_ASN1_STRING_set(dest, src->data, src->length) != + 1)) { + ret = 0; + } + if (ret == 1) { + /* Copy simple fields. */ + dest->type = src->type; + dest->flags = src->flags; + } + + return ret; +} + +/* Duplicate an ASN.1 STRING object. + * + * @param [in] asn1 ASN.1 STRING object to duplicate. + * @return New ASN.1 STRING object on success. + * @return NULL when asn1 is NULL or dynamic memory allocation fails. + */ +WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_dup(WOLFSSL_ASN1_STRING* asn1) +{ + WOLFSSL_ASN1_STRING* dupl = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_dup"); + + /* Check we have an object to duplicate. */ + if (asn1 == NULL) { + WOLFSSL_MSG("Bad parameter"); + } + else { + /* Create a new ASN.1 STRING object. */ + dupl = wolfSSL_ASN1_STRING_new(); + if (dupl == NULL) { + WOLFSSL_MSG("wolfSSL_ASN1_STRING_new error"); + } + } + + if (dupl != NULL) { + /* Copy the contents. */ + if (wolfSSL_ASN1_STRING_copy(dupl, asn1) != 1) { + WOLFSSL_MSG("wolfSSL_ASN1_STRING_copy error"); + /* Dispose of duplicate and return NULL. */ + wolfSSL_ASN1_STRING_free(dupl); + dupl = NULL; + } + } + + return dupl; +} + +/* Compare two ASN.1 STRING objects. + * + * Compares type when data the same. + * + * @param [in] a First ASN.1 STRING object. + * @param [in] b Second ASN.1 STRING object. + * @return Negative value when a is less than b. + * @return 0 when a equals b. + * @return Positive value when a is greater than b. + * @return -1 when a or b is NULL. + */ +int wolfSSL_ASN1_STRING_cmp(const WOLFSSL_ASN1_STRING *a, + const WOLFSSL_ASN1_STRING *b) +{ + int ret; + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_cmp"); + + /* Validate parameters. */ + if ((a == NULL) || (b == NULL)) { + ret = -1; + } + /* Compare length of data. */ + else if (a->length != b->length) { + ret = a->length - b->length; + } + /* Compare data. */ + else if ((ret = XMEMCMP(a->data, b->data, a->length)) == 0) { + /* Compare ASN.1 types - wolfSSL_ASN1_STRING_type_new(). */ + ret = a->type - b->type; + } + + return ret; +} + +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_EXTRA) +#if !defined(NO_CERTS) +#ifndef NO_WOLFSSL_STUB +WOLFSSL_ASN1_STRING* wolfSSL_d2i_DISPLAYTEXT(WOLFSSL_ASN1_STRING **asn, + const unsigned char **in, long len) +{ + WOLFSSL_STUB("d2i_DISPLAYTEXT"); + (void)asn; + (void)in; + (void)len; + return NULL; +} +#endif +#endif /* !NO_CERTS */ +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_ASN +#if defined(OPENSSL_EXTRA) +/* Convert ASN.1 STRING that is UniversalString type to PrintableString type. + * + * @param [in, out] s ASN.1 STRING object to convert. + * @return 1 on success. + * @return 0 when s is NULL. + * @return 0 when type is not UniversalString or string is not of that format. + */ +int wolfSSL_ASN1_UNIVERSALSTRING_to_string(WOLFSSL_ASN1_STRING *s) +{ + int ret = 1; + char* p; + char* copy; + + WOLFSSL_ENTER("wolfSSL_ASN1_UNIVERSALSTRING_to_string"); + + /* Validate parameter. */ + if (s == NULL) { + WOLFSSL_MSG("Bad parameter"); + ret = 0; + } + + /* Check type of ASN.1 STRING. */ + if ((ret == 1) && (s->type != V_ASN1_UNIVERSALSTRING)) { + WOLFSSL_MSG("Input is not a universal string"); + ret = 0; + } + + /* Check length is indicative of UNIVERSAL_STRING. */ + if ((ret == 1) && ((s->length % 4) != 0)) { + WOLFSSL_MSG("Input string must be divisible by 4"); + ret = 0; + } + + if (ret == 1) { + /* Ensure each UniversalString character looks right. */ + for (p = s->data; p < s->data + s->length; p += 4) + if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0')) + break; + /* Check whether we failed loop early. */ + if (p != s->data + s->length) { + WOLFSSL_MSG("Wrong string format"); + ret = 0; + } + } + + if (ret == 1) { + /* Strip first three bytes of each four byte character. */ + for (copy = p = s->data; p < s->data + s->length; p += 4) { + *copy++ = p[3]; + } + /* Place NUL on end. */ + *copy = '\0'; + /* Update length and type. */ + s->length /= 4; + s->type = V_ASN1_PRINTABLESTRING; + } + + return ret; +} +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Convert ASN.1 STRING to UTF8 encoding. + * + * Assumes stored encoding is UTF8. + * Returned buffer should be freed using OPENSSL_free(). + * + * @param [out] out Pointer to return allocated string. + * @param [in] asn1 ASN.1 STRING object. + * @return Length of string, excluding NUL, on success. + * @return -1 when out or asn1 is NULL. + * @return -1 when no data to return. + * @return -1 dynamic memory allocation fails. + */ +int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *asn1) +{ + unsigned char* buf = NULL; + unsigned char* data = NULL; + int len = -1; + + /* Validate parameters. */ + if ((out != NULL) && (asn1 != NULL)) { + /* Get data and length. */ + data = wolfSSL_ASN1_STRING_data(asn1); + len = wolfSSL_ASN1_STRING_length(asn1); + /* Check data and length are usable. */ + if ((data == NULL) || (len < 0)) { + len = -1; + } + } + if (len != -1) { + /* Allocate buffer to hold string and NUL. */ + buf = (unsigned char*)XMALLOC(len + 1, NULL, DYNAMIC_TYPE_OPENSSL); + if (buf == NULL) { + len = -1; + } + } + if (len != -1) { + /* Copy in string - NUL always put on end of stored string. */ + XMEMCPY(buf, data, len + 1); + /* Return buffer. */ + *out = buf; + } + + return len; +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_EXTRA) + +/* Encode ASN.1 STRING data as hex digits separated by colon. + * + * Assumes length is greater than 0. + * + * @param [in] s ASN.1 STRING object. + * @return Buffer cotaining string representation on success. + * @return NULL when dynamic memory allocation fails. + * @return NULL when encoding a character as hex fails. + */ +static char* wolfssl_asn1_string_to_hex_chars(const WOLFSSL_ASN1_STRING *s) +{ + char* tmp; + int tmpSz = s->length * 3; + + tmp = (char*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Memory Error"); + } + else { + int i; + unsigned char* str = (unsigned char*)s->data; + + /* Put out all but last character as a hex digit with ':'. */ + for (i = 0; i < s->length; i++) { + /* Put in hex digit string at end of tmp. */ + ByteToHexStr(str[i], tmp + i * 3); + /* Check not last character. */ + if (i < s->length - 1) { + /* Put in separator: ':'. */ + tmp[i * 3 + 2] = ':'; + } + /* Last character. */ + else { + /* Put in NUL to terminate string. */ + tmp[i * 3 + 2] = '\0'; + } + } + } + + return tmp; +} + +/* Create a string encoding of ASN.1 STRING object. + * + * @param [in] method Method table. Unused. + * @param [in] s ASN.1 STRING object. + * @return Buffer containing string representation on success. + * @return NULL when s or data is NULL. + * @return NULL when dynamic memory allocation fails. + * @return NULL when encoding a character as hex fails. + */ +char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method, + const WOLFSSL_ASN1_STRING *s) +{ + char* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_i2s_ASN1_STRING"); + (void)method; + + /* Validate parameters. */ + if ((s == NULL) || (s->data == NULL)) { + WOLFSSL_MSG("Bad Function Argument"); + } + /* Handle 0 length data separately. */ + else if (s->length == 0) { + ret = XMALLOC(1, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ret != NULL) { + ret[0] = '\0'; + } + } + else { + /* Convert unreadable strings to hexdecimal. */ + ret = wolfssl_asn1_string_to_hex_chars(s); + } + + return ret; +} +#endif /* OPENSSL_EXTRA */ +#endif /* NO_ASN */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Get the type of encoding. + * + * @param [in] asn1 ASN.1 STRING object. + * @return Encoding type on success. + * @return 0 when asn1 is NULL or no encoding set. + */ +int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING* asn1) +{ + int type = 0; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type"); +#endif + + if (asn1 != NULL) { + type = asn1->type; + } + + return type; +} + +#ifndef NO_CERTS +/* Get the pointer that is the data. + * + * @param [in] asn ASN.1 STRING object. + * @return Buffer with string on success. + * @return NULL when asn is NULL or no data set. + */ +const unsigned char* wolfSSL_ASN1_STRING_get0_data( + const WOLFSSL_ASN1_STRING* asn) +{ + char* data = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_get0_data"); + + if (asn != NULL) { + data = asn->data; + } + + return (const unsigned char*)data; +} + +/* Get the pointer that is the data. + * + * @param [in] asn ASN.1 STRING object. + * @return Buffer with string on success. + * @return NULL when asn is NULL or no data set. + */ +unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn) +{ + char* data = NULL; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data"); +#endif + + if (asn != NULL) { + data = asn->data; + } + + return (unsigned char*)data; +} + +/* Get the length of the data. + * + * @param [in] asn ASN.1 STRING object. + * @return String length on success. + * @return 0 when asn is NULL or no data set. + */ +int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn) +{ + int len = 0; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length"); +#endif + + if (asn) { + len = asn->length; + } + + return len; +} +#endif /* !NO_CERTS */ + +/* Set the string data. + * + * When sz is less than 0, the string length will be calculated using XSTRLEN. + * + * @param [in, out] asn1 ASN.1 STRING object. + * @param [in] data String data to set. + * @param [in] sz Length of data to set in bytes. + * @return 1 on success. + * @return 0 when asn1 is NULL or data is NULL and sz is not zero. + * @return 0 when dynamic memory allocation fails. + */ +int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, int sz) +{ + int ret = 1; + +#ifdef WOLFSSL_DEBUG_OPENSSL + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set"); +#endif + + /* Validate parameters. */ + if ((asn1 == NULL) || ((data == NULL) && (sz != 0))) { + ret = 0; + } + + /* Calculate size from data if not passed in. */ + if ((ret == 1) && (sz < 0)) { + sz = (int)XSTRLEN((const char*)data); + if (sz < 0) { + ret = 0; + } + } + + if (ret == 1) { + /* Dispose of any existing dynamic data. */ + if (asn1->isDynamic) { + XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); + asn1->data = NULL; + } + + /* Check string will fit - including NUL. */ + if (sz + 1 > CTC_NAME_SIZE) { + /* Allocate new buffer. */ + asn1->data = (char*)XMALLOC(sz + 1, NULL, DYNAMIC_TYPE_OPENSSL); + if (asn1->data == NULL) { + ret = 0; + } + else { + /* Ensure buffer will be freed. */ + asn1->isDynamic = 1; + } + } + else { + /* Clear out fixed array and use it for data. */ + XMEMSET(asn1->strData, 0, CTC_NAME_SIZE); + asn1->data = asn1->strData; + asn1->isDynamic = 0; + } + } + if (ret == 1) { + /* Check if there is a string to copy. */ + if (data != NULL) { + /* Copy string and append NUL. */ + XMEMCPY(asn1->data, data, sz); + asn1->data[sz] = '\0'; + } + /* Set size of string. */ + asn1->length = sz; + } + + return ret; +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(WOLFCRYPT_ONLY) +#ifndef NO_CERTS + +/* Make a UTF8 canonical version of ASN.1 STRING object's data. + * + * @param [in, out] asn ASN.1 STRING to set. + */ +static void wolfssl_asn1_string_canonicalize(WOLFSSL_ASN1_STRING* asn) +{ + char* src = asn->data; + char* p = asn->data + asn->length - 1; + int len = asn->length; + int i; + + /* Trim whitespace from the tail. */ + for (; (len > 0) && (XISSPACE((unsigned char)*p)); len--) { + p--; + } + if (len > 0) { + /* Trim whitespace from the head. */ + for (; XISSPACE((unsigned char)*src); len--) { + src++; + } + } + + /* Output at the start. */ + p = asn->data; + /* Process each character in string after trim. */ + for (i = 0; i < len; p++, i++) { + /* Check for non-ascii character. */ + if (!XISASCII(*src)) { + /* Keep non-ascii character as-is. */ + *p = *src++; + } + /* Check for whitespace. */ + else if (XISSPACE((unsigned char)*src)) { + /* Only use space character for whitespace. */ + *p = 0x20; + /* Skip any succeeding whitespace characters. */ + while (XISSPACE((unsigned char)*++src)) { + i++; + } + } + else { + /* Convert to lower case. */ + *p = (char)XTOLOWER((unsigned char)*src++); + } + } + /* Set actual length after canonicalization. */ + asn->length = (int)(p - asn->data); +} + +/* Make a canonical version of ASN.1 STRING object in ASN.1 STRING object. + * + * @param [in, out] asn_out ASN.1 STRING object to set. + * @param [in] asn_in ASN.1 STRING object to get data from. + * @return 1 on success. + * @return BAD_FUNC_ARG when asn_out or asn_in is NULL. + * @return 0 when no data. + * @return 0 when dynamic memory allocation fails. + */ +int wolfSSL_ASN1_STRING_canon(WOLFSSL_ASN1_STRING* asn_out, + const WOLFSSL_ASN1_STRING* asn_in) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_canon"); + + /* Validate parameters. */ + if ((asn_out == NULL) || (asn_in == NULL)) { + WOLFSSL_MSG("invalid function arguments"); + ret = BAD_FUNC_ARG; + } + + if (ret == 1) { + switch (asn_in->type) { + case MBSTRING_UTF8: + case V_ASN1_PRINTABLESTRING: + /* Set type to UTF8. */ + asn_out->type = MBSTRING_UTF8; + /* Dispose of any dynamic data already in asn_out. */ + if (asn_out->isDynamic) { + XFREE(asn_out->data, NULL, DYNAMIC_TYPE_OPENSSL); + asn_out->data = NULL; + } + /* Make ASN.1 STRING into UTF8 buffer. */ + asn_out->length = wolfSSL_ASN1_STRING_to_UTF8( + (unsigned char**)&asn_out->data, + (WOLFSSL_ASN1_STRING*)asn_in); + /* Check for error from creating UTF8 string. */ + if (asn_out->length < 0) { + ret = 0; + } + else { + /* Data now dynamic after converting to UTF8. */ + asn_out->isDynamic = 1; + /* Canonicalize the data. */ + wolfssl_asn1_string_canonicalize(asn_out); + if (asn_out->length == 0) { + /* Dispose of data if canonicalization removes all + * characters. */ + XFREE(asn_out->data, NULL, DYNAMIC_TYPE_OPENSSL); + asn_out->data = NULL; + asn_out->isDynamic = 0; + } + } + break; + default: + /* Unrecognized format - just copy. */ + WOLFSSL_MSG("just copy string"); + ret = wolfSSL_ASN1_STRING_copy(asn_out, asn_in); + } + } + + return ret; +} + +#endif /* !NO_CERTS */ +#endif /* (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) && !WOLFCRYPT_ONLY */ + +#if defined(OPENSSL_EXTRA) + +#if !defined(NO_ASN) +#ifndef NO_BIO +/* Returns boolean indicating character is unprintable. + * + * @param [in] c ASCII character. + * @return 1 when character is unprintable. + * @return 0 when character is printable. + */ +static int wolfssl_unprintable_char(char c) +{ + const unsigned char last_unprintable = 31; + const unsigned char LF = 10; /* Line Feed */ + const unsigned char CR = 13; /* Carriage Return */ + + return (c <= last_unprintable) && (c != LF) && (c != CR); +} + +/* Print ASN.1 STRING to BIO. + * + * TODO: Unprintable characters conversion is destructive. + * + * @param [in] bio BIO to print to. + * @param [in] str ASN.1 STRING to print. + * @return Length of string written on success. + * @return 0 when bio or str is NULL. + * @return 0 when writing to BIO fails. + */ +int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *bio, WOLFSSL_ASN1_STRING *str) +{ + int len = 0; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_print"); + + /* Validate parameters. */ + if ((bio != NULL) && (str != NULL)) { + int i; + + len = str->length; + /* Convert all unprintable characters to '.'. */ + for (i = 0; i < len; i++) { + if (wolfssl_unprintable_char(str->data[i])) { + str->data[i] = '.'; + } + } + /* Write string to BIO. */ + if (wolfSSL_BIO_write(bio, str->data, len) != len) { + len = 0; + } + } + + return len; +} +#endif /* !NO_BIO */ +#endif /* !NO_ASN */ + +/* Get a string for the ASN.1 tag. + * + * @param [in] tag ASN.1 tag. + * @return A string. + */ +const char* wolfSSL_ASN1_tag2str(int tag) +{ + static const char *const tag_label[31] = { + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL", + "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED", + "", "UTF8STRING", "", "", "", + "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", + "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING", + "", "BMPSTRING" + }; + const char* str = "(unknown)"; + + /* Clear negative flag. */ + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) { + tag &= ~V_ASN1_NEG; + } + /* Check for known basic types. */ + if ((tag >= 0) && (tag <= 30)) { + str = tag_label[tag]; + } + + return str; +} + +#ifndef NO_BIO + +/* Print out ASN.1 tag for the ASN.1 STRING to the BIO. + * + * @param [in] bio BIO to write to. + * @param [in] str ASN.1 STRING object. + * @return Number of characters written on success. + * @return 0 when BIO write fails. + */ +static int wolfssl_string_print_type(WOLFSSL_BIO *bio, WOLFSSL_ASN1_STRING *str) +{ + int type_len; + const char *tag; + + /* Get tag and string length. */ + tag = wolfSSL_ASN1_tag2str(str->type); + type_len = (int)XSTRLEN(tag); + /* Write tag to BIO. */ + if (wolfSSL_BIO_write(bio, tag, type_len) != type_len){ + type_len = 0; + } + /* Write colon after tag string. */ + else if (wolfSSL_BIO_write(bio, ":", 1) != 1) { + type_len = 0; + } + else { + /* Written colon - update count. */ + type_len++; + } + + return type_len; +} + +/* Dump hex digit representation of each string character to BIO. + * + * TODO: Assumes length is only one byte ie less than 128 characters long. + * + * @param [in] bio BIO to write to. + * @param [in] str ASN.1 STRING object. + * @param [in] asDer Whether to write out as a DER encoding. + * @return Number of characters written to BIO on success. + * @return -1 when writing to BIO fails. + */ +static int wolfssl_asn1_string_dump_hex(WOLFSSL_BIO *bio, + WOLFSSL_ASN1_STRING *str, int asDer) +{ + const char* hash="#"; + char hex_tmp[4]; + char* p; + char* end; + int str_len = 1; + + /* Write out hash character to indicate hex string. */ + if (wolfSSL_BIO_write(bio, hash, 1) != 1) { + str_len = -1; + } + else { + /* Check if we are to write out DER header. */ + if (asDer) { + /* Encode tag and length as hex into temporary. */ + ByteToHexStr((byte)str->type, &hex_tmp[0]); + ByteToHexStr((byte)str->length, &hex_tmp[2]); + /* Update count of written characters: tag and length. */ + str_len += 4; + /* Write out tag and length as hex digits. */ + if (wolfSSL_BIO_write(bio, hex_tmp, 4) != 4) { + str_len = -1; + } + } + } + + if (str_len != -1) { + /* Calculate end of string. */ + end = str->data + str->length - 1; + for (p = str->data; p <= end; p++) { + /* Encode string characther as hex into temporary. */ + ByteToHexStr((byte)*p, hex_tmp); + /* Update count of written characters. */ + str_len += 2; + /* Write out character as hex digites. */ + if (wolfSSL_BIO_write(bio, hex_tmp, 2) != 2) { + str_len = -1; + break; + } + } + } + + return str_len; +} + +/* Check whether character needs to be escaped. + * + * @param [in] c Character to check for. + * @param [in] str String to check. + * @return 1 when character found. + * @return 0 when characther not found. + */ +static int wolfssl_check_esc_char(char c) +{ + int ret = 0; + const char esc_ch[] = "+;<>\\"; + const char* p = esc_ch; + + /* Check if character matches any of those needing escaping. */ + for (; (*p) != '\0'; p++) { + /* Check if character matches escape character. */ + if (c == (*p)) { + ret = 1; + break; + } + } + + return ret; +} + +/* Print out string, with escaping for special characters, to BIO. + * + * @param [in] bio BIO to write to. + * @param [in] str ASN.1 STRING object. + * @return Number of characters written to BIO on success. + * @return -1 when writing to BIO fails. + */ +static int wolfssl_asn1_string_print_esc_2253(WOLFSSL_BIO *bio, + WOLFSSL_ASN1_STRING *str) +{ + char* p; + int str_len = 0; + + /* Write all of string character by character. */ + for (p = str->data; (*p) != '\0'; p++) { + /* Check if character needs escaping. */ + if (wolfssl_check_esc_char(*p)){ + /* Update count of written characters. */ + str_len++; + /* Write out escaping character. */ + if (wolfSSL_BIO_write(bio,"\\", 1) != 1) { + str_len = -1; + break; + } + } + /* Update count of written characters. */ + str_len++; + /* Write out character. */ + if (wolfSSL_BIO_write(bio, p, 1) != 1) { + str_len = -1; + break; + } + } + + return str_len; +} + +/* Extended print ASN.1 STRING to BIO. + * + * @param [in] bio BIO to print to. + * @param [in] str ASN.1 STRING to print. + * @param [in] flags Flags describing output format. + * @return Length of string written on success. + * @return 0 when bio or str is NULL. + * @return 0 when writing to BIO fails. + */ +int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *bio, WOLFSSL_ASN1_STRING *str, + unsigned long flags) +{ + int err = 0; + int str_len = -1; + int type_len = 0; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex"); + + /* Validate parameters. */ + if ((bio == NULL) || (str == NULL)) { + err = 1; + } + /* Check if ASN.1 type is to be printed. */ + if ((!err) && (flags & ASN1_STRFLGS_SHOW_TYPE)) { + /* Print type and colon to BIO. */ + type_len = wolfssl_string_print_type(bio, str); + if (type_len == 0) { + err = 1; + } + } + + if (!err) { + if (flags & ASN1_STRFLGS_DUMP_ALL) { + /* Dump hex. */ + str_len = wolfssl_asn1_string_dump_hex(bio, str, + flags & ASN1_STRFLGS_DUMP_DER); + } + else if (flags & ASN1_STRFLGS_ESC_2253) { + /* Print out string with escaping. */ + str_len = wolfssl_asn1_string_print_esc_2253(bio, str); + } + else { + /* Get number of characters to write. */ + str_len = str->length; + /* Print out string as is. */ + if (wolfSSL_BIO_write(bio, str->data, str_len) != str_len) { + err = 1; + } + } + } + + if ((!err) && (str_len != -1)) { + /* Include any characters written for type. */ + str_len += type_len; + } + else { + str_len = 0; + } + + return str_len; +} + +#endif /* !NO_BIO */ + +#endif /* OPENSSL_EXTRA */ + +/******************************************************************************* + * ASN1_GENERALIZEDTIME APIs + ******************************************************************************/ + +#ifdef OPENSSL_EXTRA + +/* Free the static ASN.1 GENERALIZED TIME object. + * + * Not an OpenSSL compatibility API. + * + * @param [in] asn1Time ASN.1 GENERALIZED TIME object. + */ +void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free"); + if (asn1Time != NULL) { + XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data)); + } +} + +#ifndef NO_BIO +/* Return the month as a string. + * + * Assumes n is '01'-'12'. + * + * @param [in] n The number of the month as a two characters (1 based). + * @return Month as a string. + */ +static WC_INLINE const char* MonthStr(const char* n) +{ + static const char monthStr[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + const char* month = "BAD"; + int i; + + i = (n[0] - '0') * 10 + (n[1] - '0') - 1; + /* Convert string to number and index table. */ + if ((i >= 0) && (i <= 12)) { + month = monthStr[i]; + } + + return month; +} + +/* Print an ASN.1 GENERALIZED TIME to a BIO. + * + * @param [in] bio BIO to write to. + * @param [in] asnTime ASN.1 GENERALIZED TIME object. + * @return 1 on success. + * @return 0 when ASN.1 GENERALIZED TIME type is invalid. + * @return 0 when writing to BIO fails. + * @return BAD_FUNC_ARG when bio or asnTime is NULL. + */ +int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, + const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) +{ + int ret = 1; + const char* p = NULL; + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); + + /* Validate parameters. */ + if ((bio == NULL) || (asnTime == NULL)) { + ret = BAD_FUNC_ARG; + } + /* Check type is GENERALIZED TIME. */ + if ((ret == 1) && (asnTime->type != V_ASN1_GENERALIZEDTIME)) { + WOLFSSL_MSG("Error, not GENERALIZED_TIME"); + ret = 0; + } + if (ret == 1) { + /* Get the string. */ + p = (const char *)(asnTime->data); + + /* Print month as a 3 letter string. */ + if (wolfSSL_BIO_write(bio, MonthStr(p + 4), 3) != 3) { + ret = 0; + } + } + /* Print space separator. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, " ", 1) != 1)) { + ret = 0; + } + + /* Print day. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, p + 6, 2) != 2)) { + ret = 0; + } + /* Print space separator. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, " ", 1) != 1)) { + ret = 0; + } + + /* Print hour. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, p + 8, 2) != 2)) { + ret = 0; + } + /* Print time separator - colon. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, ":", 1) != 1)) { + ret = 0; + } + + /* Print minutes. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, p + 10, 2) != 2)) { + ret = 0; + } + /* Print time separator - colon. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, ":", 1) != 1)) { + ret = 0; + } + + /* Print seconds. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, p + 12, 2) != 2)) { + ret = 0; + } + /* Print space separator. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, " ", 1) != 1)) { + ret = 0; + } + /* Print year. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, p, 4) != 4)) { + ret = 0; + } + + return ret; +} +#endif /* !NO_BIO */ + +#endif /* OPENSSL_EXTRA */ + +/******************************************************************************* + * ASN1_TIME APIs + ******************************************************************************/ + +#ifndef NO_ASN_TIME + +#ifdef OPENSSL_EXTRA +/* Allocate a new ASN.1 TIME object. + * + * @return New empty ASN.1 TIME object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_new(void) +{ + WOLFSSL_ASN1_TIME* ret; + + /* Allocate a new ASN.1 TYPE object. */ + ret = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, + DYNAMIC_TYPE_OPENSSL); + if (ret != NULL) { + /* Clear out fields. */ + XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME)); + } + + return ret; +} + +/* Dispose of ASN.1 TIME object. + * + * @param [in, out] t ASN.1 TIME object. + */ +void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME* t) +{ + /* Dispose of ASN.1 TIME object. */ + XFREE(t, NULL, DYNAMIC_TYPE_OPENSSL); +} + +#ifndef NO_WOLFSSL_STUB +/* Set the Unix time GMT into ASN.1 TIME object. + * + * Not implemented. + * + * @param [in, out] a ASN.1 TIME object. + * @param [in] t Unix time GMT. + * @return An ASN.1 TIME object. + */ +WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_set(WOLFSSL_ASN1_TIME *a, time_t t) +{ + WOLFSSL_STUB("wolfSSL_ASN1_TIME_set"); + (void)a; + (void)t; + return a; +} +#endif /* !NO_WOLFSSL_STUB */ + +/* Convert time to Unix time (GMT). + * + * @param [in] sec Second in minute. 0-59. + * @param [in] minute Minute in hour. 0-59. + * @param [in] hour Hour in day. 0-23. + * @param [in] mday Day of month. 1-31. + * @param [in] mon Month of year. 0-11 + * @param [in] year Year including century. ie: 1991, 2023, 2048. + * @return Seconds since 00:00:00 01/01/1970 for the time passed in. + */ +static long long wolfssl_time_to_unix_time(int sec, int minute, int hour, + int mday, int mon, int year) +{ + /* Number of cumulative days from the previous months, starting from + * beginning of January. */ + static const int monthDaysCumulative [12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; + int leapDays = year; + + /* Leap day at end of February. */ + if (mon <= 1) { + --leapDays; + } + /* Calculate leap days. */ + leapDays = leapDays / 4 - leapDays / 100 + leapDays / 400 - 1969 / 4 + + 1969 / 100 - 1969 / 400; + + /* Calculate number of seconds. */ + return ((((long long) (year - 1970) * 365 + leapDays + + monthDaysCumulative[mon] + mday - 1) * 24 + hour) * 60 + minute) * + 60 + sec; +} + +/* Convert ASN.1 TIME object to Unix time (GMT). + * + * @param [in] t ASN.1 TIME object. + * @param [out] secs Number of seconds since 00:00:00 01/01/1970. + * @return 1 on success. + * @return 0 when conversion of time fails. + */ +static int wolfssl_asn1_time_to_secs(const WOLFSSL_ASN1_TIME* t, + long long* secs) +{ + int ret = 1; + struct tm tm_s; + struct tm *tmGmt = &tm_s; + + /* Convert ASN.1 TIME to broken-down time. NULL treated as current time. */ + ret = wolfSSL_ASN1_TIME_to_tm(t, tmGmt); + if (ret != 1) { + WOLFSSL_MSG("Failed to convert from time to struct tm."); + } + else { + /* We use wolfssl_time_to_unix_time here instead of XMKTIME to avoid the + * Year 2038 problem on platforms where time_t is 32 bits. struct tm + * stores the year as years since 1900, so we add 1900 to the year. */ + *secs = wolfssl_time_to_unix_time(tmGmt->tm_sec, tmGmt->tm_min, + tmGmt->tm_hour, tmGmt->tm_mday, tmGmt->tm_mon, + tmGmt->tm_year + 1900); + } + + return ret; +} + +/* Calculate difference in time of two ASN.1 TIME objects. + * + * @param [out] days Number of whole days between from and to. + * @param [out] secs Number of serconds less than a day between from and to. + * @param [in] from ASN.1 TIME object as start time. + * @param [in] to ASN.1 TIME object as end time. + * @return 1 on success. + * @return 0 when days or secs is NULL. + * @return 0 when conversion of time fails. + */ +int wolfSSL_ASN1_TIME_diff(int *days, int *secs, const WOLFSSL_ASN1_TIME *from, + const WOLFSSL_ASN1_TIME *to) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_diff"); + + /* Validate parameters. */ + if (days == NULL) { + WOLFSSL_MSG("days is NULL"); + ret = 0; + } + if ((ret == 1) && (secs == NULL)) { + WOLFSSL_MSG("secs is NULL"); + ret = 0; + } + + if ((ret == 1) && ((from == NULL) && (to == NULL))) { + *days = 0; + *secs = 0; + } + else if (ret == 1) { + const int SECS_PER_DAY = 24 * 60 * 60; + long long fromSecs; + long long toSecs = 0; + + ret = wolfssl_asn1_time_to_secs(from, &fromSecs); + if (ret == 1) { + ret = wolfssl_asn1_time_to_secs(to, &toSecs); + } + if (ret == 1) { + double diffSecs = (double)(toSecs - fromSecs); + *days = (int) (diffSecs / SECS_PER_DAY); + *secs = (int) (diffSecs - (((double)*days) * SECS_PER_DAY)); + } + } + + return ret; +} + +/* Compare two ASN.1 TIME objects by comparing time value. + * + * @param [in] a First ASN.1 TIME object. + * @param [in] b Second ASN.1 TIME object. + * @return Negative value when a is less than b. + * @return 0 when a equals b. + * @return Positive value when a is greater than b. + * @return -2 when a or b is invalid. + */ +int wolfSSL_ASN1_TIME_compare(const WOLFSSL_ASN1_TIME *a, + const WOLFSSL_ASN1_TIME *b) +{ + int ret; + int days; + int secs; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_compare"); + + /* Calculate difference in time between a and b. */ + if (wolfSSL_ASN1_TIME_diff(&days, &secs, a, b) != 1) { + WOLFSSL_MSG("Failed to get time difference."); + ret = -2; + } + else if (days == 0 && secs == 0) { + /* a and b are the same time. */ + ret = 0; + } + else if (days >= 0 && secs >= 0) { + /* a is before b. */ + ret = -1; + } + /* Assume wolfSSL_ASN1_TIME_diff creates coherent values. */ + else { + ret = 1; + } + + WOLFSSL_LEAVE("wolfSSL_ASN1_TIME_compare", ret); + + return ret; +} + +#if !defined(USER_TIME) && !defined(TIME_OVERRIDES) +/* Adjust the time into an ASN.1 TIME object. + * + * @param [in] a ASN.1 TIME object. May be NULL. + * @param [in] t Time to offset. + * @param [in] offset_day Number of days to offset. May be negative. + * @param [in] offset_sec Number of seconds to offset. May be negative. + * @return ASN.1 TIME object on success. + * @return NULL when formatting time fails. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME* a, time_t t, + int offset_day, long offset_sec) +{ + WOLFSSL_ASN1_TIME* ret = NULL; + const time_t sec_per_day = 24*60*60; + int time_get; + char time_str[MAX_TIME_STRING_SZ]; + time_t offset_day_sec = offset_day * sec_per_day; + time_t t_adj = t + offset_day_sec + offset_sec; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj"); + + /* Get time string as either UTC or GeneralizedTime. */ + time_get = GetFormattedTime(&t_adj, (byte*)time_str, MAX_TIME_STRING_SZ); + if (time_get > 0) { + ret = a; + if (ret == NULL) { + ret = wolfSSL_ASN1_TIME_new(); + } + /* Set the string into the ASN.1 TIME object. */ + if ((wolfSSL_ASN1_TIME_set_string(ret, time_str) != 1) && (ret != a)) { + wolfSSL_ASN1_TIME_free(ret); + ret = NULL; + } + } + + return ret; +} +#endif /* !USER_TIME && !TIME_OVERRIDES */ + +/* Get the length of the ASN.1 TIME data. + * + * Not an OpenSSL function - ASN1_TIME is not opaque. + * + * @param [in] t ASN.1 TIME object. + * @return Length of data on success. + * @return 0 when t is NULL or no time set. + */ +int wolfSSL_ASN1_TIME_get_length(const WOLFSSL_ASN1_TIME *t) +{ + int len = 0; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length"); + + if (t != NULL) { + len = t->length; + } + + return len; +} + +/* Get the data from the ASN.1 TIME object. + * + * Not an OpenSSL function - ASN1_TIME is not opaque. + * + * @param [in] t ASN.1 TIME object. + * @return Data buffer on success. + * @return NULL when t is NULL. + */ +unsigned char* wolfSSL_ASN1_TIME_get_data(const WOLFSSL_ASN1_TIME *t) +{ + unsigned char* data = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data"); + + if (t != NULL) { + data = (unsigned char*)t->data; + } + + return data; +} + +/* Check format of string in ASN.1 TIME object. + * + * @param [in] a ASN.1 TIME object. + * @return 1 on success. + * @return 0 when format invalid. + */ +int wolfSSL_ASN1_TIME_check(const WOLFSSL_ASN1_TIME* a) +{ + int ret = 1; + char buf[MAX_TIME_STRING_SZ]; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_check"); + + /* If can convert to human readable then format good. */ + if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)a, buf, + MAX_TIME_STRING_SZ) == NULL) { + ret = 0; + } + + return ret; +} + +/* Set the time as a string into ASN.1 TIME object. + * + * When t is NULL, str is checked only. + * + * @param [in, out] t ASN.1 TIME object. + * @param [in] str Time as a string. + * @return 1 on success. + * @return 0 when str is NULL. + * @return 0 when str is not formatted correctly. + */ +int wolfSSL_ASN1_TIME_set_string(WOLFSSL_ASN1_TIME *t, const char *str) +{ + int ret = 1; + int slen = 0; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_set_string"); + + if (str == NULL) { + WOLFSSL_MSG("Bad parameter"); + ret = 0; + } + if (ret == 1) { + /* Get length of string including NUL terminator. */ + slen = (int)XSTRLEN(str) + 1; + if (slen > CTC_DATE_SIZE) { + WOLFSSL_MSG("Date string too long"); + ret = 0; + } + } + if ((ret == 1) && (t != NULL)) { + /* Copy in string including NUL terminator. */ + XMEMCPY(t->data, str, slen); + /* Do not include NUL terminator in length. */ + t->length = slen - 1; + /* Set ASN.1 type based on string length. */ + t->type = ((slen == ASN_UTC_TIME_SIZE) ? V_ASN1_UTCTIME : + V_ASN1_GENERALIZEDTIME); + } + + return ret; +} + +/* Convert ASN.1 TIME object to ASN.1 GENERALIZED TIME object. + * + * @param [in] t ASN.1 TIME object. + * @param [in, out] out ASN.1 GENERALIZED TIME object. + * @return ASN.1 GENERALIZED TIME object on success. + * @return NULL when t is NULL or t has wrong ASN.1 type. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, + WOLFSSL_ASN1_TIME **out) +{ + WOLFSSL_ASN1_TIME *ret = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime"); + + /* Validate parameters. */ + if (t == NULL) { + WOLFSSL_MSG("Invalid ASN_TIME value"); + } + /* Ensure ASN.1 type is one that is supported. */ + else if ((t->type != V_ASN1_UTCTIME) && + (t->type != V_ASN1_GENERALIZEDTIME)) { + WOLFSSL_MSG("Invalid ASN_TIME type."); + } + /* Check for ASN.1 GENERALIZED TIME object being passed in. */ + else if ((out != NULL) && (*out != NULL)) { + /* Copy into the passed in object. */ + ret = *out; + } + else { + /* Create a new ASN.1 GENERALIZED TIME object. */ + ret = wolfSSL_ASN1_TIME_new(); + if (ret == NULL) { + WOLFSSL_MSG("memory alloc failed."); + } + } + + if (ret != NULL) { + /* Set the ASN.1 type and length of string. */ + ret->type = V_ASN1_GENERALIZEDTIME; + ret->length = ASN_GENERALIZED_TIME_SIZE; + + if (t->type == V_ASN1_GENERALIZEDTIME) { + /* Just copy as data already appropriately formatted. */ + XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE); + } + else { + /* Convert UTC TIME to GENERALIZED TIME. */ + if (t->data[0] >= '5') { + /* >= 50 is 1900s. */ + ret->data[0] = '1'; ret->data[1] = '9'; + } + else { + /* < 50 is 2000s. */ + ret->data[0] = '2'; ret->data[1] = '0'; + } + /* Append rest of the data as it is the same. */ + XMEMCPY(&ret->data[2], t->data, ASN_UTC_TIME_SIZE); + } + + /* Check for pointer to return result through. */ + if (out != NULL) { + *out = ret; + } + } + + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) +/* Get string from ASN.1 TIME object. + * + * Not an OpenSSL compatibility API. + * + * @param [in] t ASN.1 TIME object. + * @param [in, out] buf Buffer to put string in. + * @param [in] len Length of buffer in bytes. + * @return buf on success. + * @return NULL when t or buf is NULL, or len is less than 5. + * @return NULL when ASN.1 TIME length is larger than len. + * @return NULL when internal time format not valid. + */ +char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); + + /* Validate parameters. */ + if ((t == NULL) || (buf == NULL) || (len < 5)) { + WOLFSSL_MSG("Bad argument"); + buf = NULL; + } + + /* Check internal length against passed in length. */ + if ((buf != NULL) && (t->length > len)) { + WOLFSSL_MSG("Length of date is longer then buffer"); + buf = NULL; + } + + /* Get time as human readable string. */ + if ((buf != NULL) && !GetTimeString(t->data, t->type, buf, len)) { + buf = NULL; + } + + return buf; +} + +/* Number of characters in a UTC TIME string. */ +#define UTCTIME_LEN 13 + +/* Get year from UTC TIME string. + * + * @param [in] str UTC TIME string. + * @param [in] len Length of string in bytes. + * @param [out] year Year as extracted from string. + * @return 1 on success. + * @return 0 when length is too short for a UTC TIME. + * @return 0 when not ZULU time. + */ +static int wolfssl_utctime_year(const unsigned char* str, int len, int* year) +{ + int ret = 1; + + /* Check minimal length for UTC TIME. */ + if (len < UTCTIME_LEN) { + WOLFSSL_MSG("WOLFSSL_ASN1_TIME buffer length is invalid."); + ret = 0; + } + /* Only support ZULU time. */ + if ((ret == 1) && (str[UTCTIME_LEN - 1] != 'Z')) { + WOLFSSL_MSG("Expecting UTC time."); + ret = 0; + } + + if (ret == 1) { + int tm_year; + /* 2-digit year. */ + tm_year = (str[0] - '0') * 10; + tm_year += str[1] - '0'; + /* Check for year being in the 2000s. */ + if (tm_year < 50) { + tm_year += 100; + } + *year = tm_year; + } + + return ret; +} + +/* Number of characters in a GENERALIZED TIME string. */ +#define GENTIME_LEN 15 + +/* Get year from GENERALIZED TIME string. + * + * @param [in] str GENERALIZED TIME string. + * @param [in] len Length of string in bytes. + * @param [out] year Year as extracted from string. + * @return 1 on success. + * @return 0 when length is too short for a GENERALIZED TIME. + * @return 0 when not ZULU time. + */ +static int wolfssl_gentime_year(const unsigned char* str, int len, int* year) +{ + int ret = 1; + + /* Check minimal length for GENERALIZED TIME. */ + if (len < GENTIME_LEN) { + WOLFSSL_MSG("WOLFSSL_ASN1_TIME buffer length is invalid."); + ret = 0; + } + if ((ret == 1) && (str[GENTIME_LEN - 1] != 'Z')) { + WOLFSSL_MSG("Expecting Generalized time."); + ret = 0; + } + + if (ret == 1) { + int tm_year; + /* 4-digit year. */ + tm_year = (str[0] - '0') * 1000; + tm_year += (str[1] - '0') * 100; + tm_year += (str[2] - '0') * 10; + tm_year += str[3] - '0'; + /* Only need value to be years since 1900. */ + tm_year -= 1900; + *year = tm_year; + } + + return ret; +} + +/* Convert an ASN.1 TIME to a struct tm. + * + * @param [in] asnTime ASN.1 TIME object. + * @param [in] tm Broken-down time. Must be non-NULL. + * @return 1 on success. + * @return 0 when string format is invalid. + */ +static int wolfssl_asn1_time_to_tm(const WOLFSSL_ASN1_TIME* asnTime, + struct tm* tm) +{ + int ret = 1; + const unsigned char* asn1TimeBuf; + int asn1TimeBufLen; + int i = 0; + + /* Get the string buffer - fixed array, can't fail. */ + asn1TimeBuf = wolfSSL_ASN1_TIME_get_data(asnTime); + /* Get the length of the string. */ + asn1TimeBufLen = wolfSSL_ASN1_TIME_get_length(asnTime); + if (asn1TimeBufLen <= 0) { + WOLFSSL_MSG("Failed to get WOLFSSL_ASN1_TIME buffer length."); + ret = 0; + } + if (ret == 1) { + /* Zero out values in broken-down time. */ + XMEMSET(tm, 0, sizeof(struct tm)); + + if (asnTime->type == V_ASN1_UTCTIME) { + /* Get year from UTC TIME string. */ + if ((ret = wolfssl_utctime_year(asn1TimeBuf, asn1TimeBufLen, + &tm->tm_year)) == 1) { + /* Month starts after year - 2 characters. */ + i = 2; + } + } + else if (asnTime->type == V_ASN1_GENERALIZEDTIME) { + /* Get year from GENERALIZED TIME string. */ + if ((ret = wolfssl_gentime_year(asn1TimeBuf, asn1TimeBufLen, + &tm->tm_year)) == 1) { + /* Month starts after year - 4 characters. */ + i = 4; + } + } + else { + /* No other time formats known. */ + WOLFSSL_MSG("asnTime->type is invalid."); + ret = 0; + } + } + if (ret == 1) { + /* Fill in rest of broken-down time from string. */ + /* January is 0 not 1 */ + tm->tm_mon = (asn1TimeBuf[i] - '0') * 10; i++; + tm->tm_mon += (asn1TimeBuf[i] - '0') - 1; i++; + tm->tm_mday = (asn1TimeBuf[i] - '0') * 10; i++; + tm->tm_mday += (asn1TimeBuf[i] - '0'); i++; + tm->tm_hour = (asn1TimeBuf[i] - '0') * 10; i++; + tm->tm_hour += (asn1TimeBuf[i] - '0'); i++; + tm->tm_min = (asn1TimeBuf[i] - '0') * 10; i++; + tm->tm_min += (asn1TimeBuf[i] - '0'); i++; + tm->tm_sec = (asn1TimeBuf[i] - '0') * 10; i++; + tm->tm_sec += (asn1TimeBuf[i] - '0'); + + #ifdef XMKTIME + /* Call XMKTIME on tm to get tm_wday and tm_yday fields populated. */ + XMKTIME(tm); + #endif + } + + return ret; +} + +/* Get the current time into a broken-down time. + * + * @param [out] tm Broken-time time. + * @return 1 on success. + * @return 0 when tm is NULL. + * @return 0 when get current time fails. + * @return 0 when converting Unix time to broken-down time fails. + */ +static int wolfssl_get_current_time_tm(struct tm* tm) +{ + int ret = 1; + time_t currentTime; + struct tm *tmpTs; +#if defined(NEED_TMP_TIME) + /* for use with gmtime_r */ + struct tm tmpTimeStorage; + tmpTs = &tmpTimeStorage; +#else + tmpTs = NULL; +#endif + (void)tmpTs; + + /* Must have a pointer to return result into. */ + if (tm == NULL) { + WOLFSSL_MSG("asnTime and tm are both NULL"); + ret = 0; + } + if (ret == 1) { + /* Get current Unix Time GMT. */ + currentTime = wc_Time(0); + if (currentTime <= 0) { + WOLFSSL_MSG("Failed to get current time."); + ret = 0; + } + } + if (ret == 1) { + /* Convert Unix Time GMT into broken-down time. */ + tmpTs = XGMTIME(¤tTime, tmpTs); + if (tmpTs == NULL) { + WOLFSSL_MSG("Failed to convert current time to UTC."); + ret = 0; + } + } + if (ret == 1) { + /* Copy from the structure returned into parameter. */ + XMEMCPY(tm, tmpTs, sizeof(*tm)); + } + + return ret; +} + +/* Convert ASN.1 TIME object's time into broken-down representation. + * + * Internal time string is checked when tm is NULL. + * + * @param [in] asnTime ASN.1 TIME object. + * @param [out] tm Broken-down time. + * @return 1 on success. + * @return 0 when asnTime is NULL and tm is NULL. + * @return 0 getting current time fails. + * @return 0 when internal time string is invalid. + */ +int wolfSSL_ASN1_TIME_to_tm(const WOLFSSL_ASN1_TIME* asnTime, struct tm* tm) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_tm"); + + /* If asnTime is NULL, then the current time is converted. */ + if (asnTime == NULL) { + ret = wolfssl_get_current_time_tm(tm); + } + /* If tm is NULL this function performs a format check on asnTime only. */ + else if (tm == NULL) { + ret = wolfSSL_ASN1_TIME_check(asnTime); + } + else { + /* Convert ASN.1 TIME to broken-down time. */ + ret = wolfssl_asn1_time_to_tm(asnTime, tm); + } + + return ret; +} + +#ifndef NO_BIO +/* Print the ASN.1 TIME object as a string to BIO. + * + * @param [in] bio BIO to write to. + * @param [in] asnTime ASN.1 TIME object. + * @return 1 on success. + * @return 0 when bio or asnTime is NULL. + * @return 0 when creating human readable string fails. + * @return 0 when writing to BIO fails. + */ +int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) +{ + char buf[MAX_TIME_STRING_SZ]; + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); + + /* Validate parameters. */ + if ((bio == NULL) || (asnTime == NULL)) { + WOLFSSL_MSG("NULL function argument"); + ret = 0; + } + + if (ret == 1) { + int len; + + /* Create human readable string. */ + if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, + sizeof(buf)) == NULL) { + /* Write out something anyway but return error. */ + XMEMSET(buf, 0, MAX_TIME_STRING_SZ); + XSTRNCPY(buf, "Bad time value", sizeof(buf)-1); + ret = 0; + } + + /* Write out string. */ + len = (int)XSTRLEN(buf); + if (wolfSSL_BIO_write(bio, buf, len) != len) { + WOLFSSL_MSG("Unable to write to bio"); + ret = 0; + } + } + + return ret; +} +#endif /* !NO_BIO */ + +#endif /* WOLFSSL_MYSQL_COMPATIBLE || OPENSSL_EXTRA */ + +#ifdef OPENSSL_EXTRA + +#ifndef NO_BIO +/* Print the ASN.1 UTC TIME object as a string to BIO. + * + * @param [in] bio BIO to write to. + * @param [in] asnTime ASN.1 UTC TIME object. + * @return 1 on success. + * @return 0 when bio or asnTime is NULL. + * @return 0 when ASN.1 type is not UTC TIME. + * @return 0 when creating human readable string fails. + * @return 0 when writing to BIO fails. + */ +int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_ASN1_UTCTIME_print"); + + /* Validate parameters. */ + if ((bio == NULL) || (a == NULL)) { + ret = 0; + } + /* Validate ASN.1 UTC TIME object is of type UTC_TIME. */ + if ((ret == 1) && (a->type != V_ASN1_UTCTIME)) { + WOLFSSL_MSG("Error, not UTC_TIME"); + ret = 0; + } + + if (ret == 1) { + /* Use generic time printing function to do work. */ + ret = wolfSSL_ASN1_TIME_print(bio, a); + } + + return ret; +} +#endif /* !NO_BIO */ + +#endif /* OPENSSL_EXTRA */ + +#endif /* !NO_ASN_TIME */ + +/******************************************************************************* + * ASN1_TYPE APIs + ******************************************************************************/ + +#ifdef OPENSSL_EXTRA + +/** + * Allocate a new ASN.1 TYPE object. + * + * @return New empty ASN.1 TYPE object on success. + * @return NULL when dynamic memory allocation fails. + */ +WOLFSSL_ASN1_TYPE* wolfSSL_ASN1_TYPE_new(void) +{ + WOLFSSL_ASN1_TYPE* ret; + + /* Allocate a new ASN.1 TYPE object. */ + ret = (WOLFSSL_ASN1_TYPE*)XMALLOC(sizeof(WOLFSSL_ASN1_TYPE), NULL, + DYNAMIC_TYPE_OPENSSL); + if (ret != NULL) { + /* Clear out fields. */ + XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TYPE)); + } + + return ret; +} + +/* Free the ASN.1 TYPE object's value field. + * + * @param [in, out] at ASN.1 TYPE object. + */ +static void wolfssl_asn1_type_free_value(WOLFSSL_ASN1_TYPE* at) +{ + switch (at->type) { + case V_ASN1_NULL: + break; + case V_ASN1_OBJECT: + wolfSSL_ASN1_OBJECT_free(at->value.object); + break; + case V_ASN1_UTCTIME: + #ifndef NO_ASN_TIME + wolfSSL_ASN1_TIME_free(at->value.utctime); + #endif + break; + case V_ASN1_GENERALIZEDTIME: + #ifndef NO_ASN_TIME + wolfSSL_ASN1_TIME_free(at->value.generalizedtime); + #endif + break; + case V_ASN1_UTF8STRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_IA5STRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_SEQUENCE: + wolfSSL_ASN1_STRING_free(at->value.asn1_string); + break; + default: + break; + } +} + +/** + * Free ASN.1 TYPE object and its value. + * + * @param [in, out] at ASN.1 TYPE object. + */ +void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at) +{ + if (at != NULL) { + /* Dispose of value in ASN.1 TYPE object. */ + wolfssl_asn1_type_free_value(at); + } + /* Dispose of ASN.1 TYPE object. */ + XFREE(at, NULL, DYNAMIC_TYPE_OPENSSL); +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_WPAS) +/** + * Set ASN.1 TYPE object with a type and value. + * + * Type of value for different types: + * V_ASN1_NULL : Value should be NULL. + * V_ASN1_OBJECT : WOLFSSL_ASN1_OBJECT. + * V_ASN1_UTCTIME : WOLFSSL_ASN1_TIME. + * V_ASN1_GENERALIZEDTIME : WOLFSSL_ASN1_TIME. + * V_ASN1_UTF8STRING : WOLFSSL_ASN1_STRING. + * V_ASN1_PRINTABLESTRING : WOLFSSL_ASN1_STRING. + * V_ASN1_T61STRING : WOLFSSL_ASN1_STRING. + * V_ASN1_IA5STRING : WOLFSSL_ASN1_STRING. + * V_ASN1_UNINVERSALSTRING: WOLFSSL_ASN1_STRING. + * V_ASN1_SEQUENCE : WOLFSSL_ASN1_STRING. + * + * @param [in, out] a ASN.1 TYPE object to set. + * @param [in] type ASN.1 type of value. + * @param [in] value Value to store. + */ +void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value) +{ + if (a != NULL) { + switch (type) { + case V_ASN1_NULL: + if (value != NULL) { + WOLFSSL_MSG("NULL tag meant to be always empty!"); + /* No way to return error - value will not be used. */ + } + /* fall-through */ + case V_ASN1_OBJECT: + case V_ASN1_UTCTIME: + case V_ASN1_GENERALIZEDTIME: + case V_ASN1_UTF8STRING: + case V_ASN1_PRINTABLESTRING: + case V_ASN1_T61STRING: + case V_ASN1_IA5STRING: + case V_ASN1_UNIVERSALSTRING: + case V_ASN1_SEQUENCE: + /* Dispose of any value currently set. */ + wolfssl_asn1_type_free_value(a); + /* Assign anonymously typed input to anonymously typed field. */ + a->value.ptr = (char *)value; + /* Set the type required. */ + a->type = type; + break; + default: + WOLFSSL_MSG("Unknown or unsupported ASN1_TYPE"); + /* No way to return error. */ + } + } +} + +#endif /* OPENSSL_ALL || WOLFSSL_WPAS */ + +#endif /* !WOLFSSL_SSL_ASN1_INCLUDED */ + diff --git a/src/ssl_bn.c b/src/ssl_bn.c index caea92027..474259688 100644 --- a/src/ssl_bn.c +++ b/src/ssl_bn.c @@ -50,6 +50,35 @@ * Constructor/Destructor/Initializer APIs ******************************************************************************/ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) +/* Set big number to be negative. + * + * @param [in, out] bn Big number to make negative. + * @param [in] neg Whether number is negative. + * @return 1 on success. + * @return -1 when bn or internal representation of bn is NULL. + */ +static int wolfssl_bn_set_neg(WOLFSSL_BIGNUM* bn, int neg) +{ + int ret = 1; + + if (BN_IS_NULL(bn)) { + WOLFSSL_MSG("bn NULL error"); + ret = -1; + } +#if !defined(WOLFSSL_SP_MATH_ALL) || defined(WOLFSSL_SP_INT_NEGATIVE) + else if (neg) { + mp_setneg((mp_int*)bn->internal); + } + else { + ((mp_int*)bn->internal)->sign = MP_ZPOS; + } +#endif + + return ret; +} +#endif /* OPENSSL_EXTRA && !NO_ASN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* Get the internal representation value into an MP integer. * diff --git a/src/x509.c b/src/x509.c index d2da2bd88..efef2954f 100644 --- a/src/x509.c +++ b/src/x509.c @@ -231,10 +231,6 @@ void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x) return; if (x->obj != NULL) { - if (x->obj->pathlen != NULL) { - wolfSSL_ASN1_INTEGER_free(x->obj->pathlen); - x->obj->pathlen = NULL; - } wolfSSL_ASN1_OBJECT_free(x->obj); } @@ -10078,7 +10074,6 @@ int wolfSSL_i2d_X509_NAME_canon(WOLFSSL_X509_NAME* name, unsigned char** out) return WOLFSSL_FATAL_ERROR; } totalBytes += ret; - wolfSSL_OPENSSL_free(cano_data->data); wolfSSL_ASN1_STRING_free(cano_data); } } diff --git a/tests/api.c b/tests/api.c index ff17b5915..2fddc90de 100644 --- a/tests/api.c +++ b/tests/api.c @@ -467,6 +467,59 @@ static int testDevId = INVALID_DEVID; #define HAVE_IO_TESTS_DEPENDENCIES #endif +/*----------------------------------------------------------------------------* + | BIO with fixed read/write size + *----------------------------------------------------------------------------*/ + +#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) + +static int wolfssl_bio_s_fixed_mem_write(WOLFSSL_BIO* bio, const char* data, + int len) +{ + if ((bio == NULL) || (bio->ptr == NULL) || (data == NULL)) { + len = 0; + } + else { + if (bio->wrSz - bio->wrIdx < len) { + len = bio->wrSz - bio->wrIdx; + } + XMEMCPY((char*)bio->ptr + bio->wrIdx, data, len); + bio->wrIdx += len; + } + + return len; +} + +static int wolfssl_bio_s_fixed_mem_read(WOLFSSL_BIO* bio, char* data, int len) +{ + if ((bio == NULL) || (bio->ptr == NULL) || (data == NULL)) { + len = 0; + } + else { + if (bio->wrSz - bio->rdIdx < len) { + len = bio->wrSz - bio->rdIdx; + } + XMEMCPY(data, (char*)bio->ptr + bio->rdIdx, len); + bio->rdIdx += len; + } + + return len; +} + +static WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_fixed_mem(void) +{ + static WOLFSSL_BIO_METHOD meth; + + meth.type = WOLFSSL_BIO_BIO; + XMEMCPY(meth.name, "Fixed Memory Size", 18); + meth.writeCb = wolfssl_bio_s_fixed_mem_write; + meth.readCb = wolfssl_bio_s_fixed_mem_read; + + return &meth; +} + +#endif + /*----------------------------------------------------------------------------* | Setup *----------------------------------------------------------------------------*/ @@ -28650,9 +28703,11 @@ static int test_wc_PKCS7_VerifySignedData(void) static const byte messageDigestOid[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; +#ifndef NO_ASN_TIME /* signingTime OID () */ static const byte signingTimeOid[] = { 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05}; +#endif #if !defined(NO_ASN) && !defined(NO_ASN_TIME) int dateLength = 0; @@ -28701,6 +28756,7 @@ static int test_wc_PKCS7_VerifySignedData(void) AssertNotNull(decodedAttrib->value); AssertIntEQ(XMEMCMP(decodedAttrib->value + 2, hashBuf, hashSz), 0); +#ifndef NO_ASN_TIME /* signingTime should be second */ decodedAttrib = decodedAttrib->next; AssertNotNull(decodedAttrib); @@ -28710,6 +28766,7 @@ static int test_wc_PKCS7_VerifySignedData(void) AssertIntGT(decodedAttrib->valueSz, 0); AssertNotNull(decodedAttrib->value); +#endif /* Verify signingTime if ASN and time are available */ #if !defined(NO_ASN) && !defined(NO_ASN_TIME) @@ -30637,6 +30694,2292 @@ static int test_wc_HashGetFlags(void) | Compatibility Tests *----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------* + | ASN.1 Tests + *----------------------------------------------------------------------------*/ + +static int test_wolfSSL_ASN1_BIT_STRING(void) +{ + int res = TEST_SKIPPED; +#if !defined(NO_CERTS) && defined(OPENSSL_ALL) + ASN1_BIT_STRING* str; + + AssertNotNull(str = ASN1_BIT_STRING_new()); + /* Empty data testing. */ + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 1), 0); + ASN1_BIT_STRING_free(str); + + AssertNotNull(str = ASN1_BIT_STRING_new()); + + /* Invalid parameter testing. */ + AssertIntEQ(ASN1_BIT_STRING_set_bit(NULL, 42, 1), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, -1, 1), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 42, 2), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 42, -1), 0); + + /* No bit string - bit is always 0. */ + AssertIntEQ(ASN1_BIT_STRING_get_bit(NULL, 42), 0); + AssertIntEQ(ASN1_BIT_STRING_get_bit(NULL, -1), 0); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, -1), 0); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 0), 0); + + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 42, 1), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 42), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 41), 0); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, -1), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 84, 1), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 84), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 83), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 91, 0), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 91), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 89, 0), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 89), 0); + AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 42, 0), 1); + AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 42), 0); + + ASN1_BIT_STRING_free(str); + ASN1_BIT_STRING_free(NULL); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_INTEGER(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER* a; + ASN1_INTEGER* dup; + const unsigned char invalidLenDer[] = { + 0x02, 0x20, 0x00 + }; + const unsigned char longDer[] = { + 0x02, 0x20, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 + }; + const unsigned char* p; + + /* Invalid parameter testing. */ + ASN1_INTEGER_free(NULL); + AssertNull(wolfSSL_ASN1_INTEGER_dup(NULL)); + + AssertNotNull(a = ASN1_INTEGER_new()); + AssertNotNull(dup = wolfSSL_ASN1_INTEGER_dup(a)); + ASN1_INTEGER_free(dup); + ASN1_INTEGER_free(a); + + p = longDer; + AssertNull(d2i_ASN1_INTEGER(NULL, &p, sizeof(invalidLenDer))); + + p = longDer; + AssertNotNull(a = d2i_ASN1_INTEGER(NULL, &p, sizeof(longDer))); + AssertPtrNE(p, longDer); + AssertNotNull(dup = wolfSSL_ASN1_INTEGER_dup(a)); + ASN1_INTEGER_free(dup); + ASN1_INTEGER_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_INTEGER_cmp(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER* a; + ASN1_INTEGER* b; + + AssertNotNull(a = ASN1_INTEGER_new()); + AssertNotNull(b = ASN1_INTEGER_new()); + AssertIntEQ(ASN1_INTEGER_set(a, 1), 1); + AssertIntEQ(ASN1_INTEGER_set(b, 1), 1); + + /* Invalid parameter testing. */ + AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(NULL, NULL), -1); + AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, NULL), -1); + AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(NULL, b), -1); + + AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); + AssertIntEQ(ASN1_INTEGER_set(b, -1), 1); + AssertIntGT(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); + AssertIntEQ(ASN1_INTEGER_set(a, -2), 1); + AssertIntLT(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); + AssertIntEQ(ASN1_INTEGER_set(b, 1), 1); + AssertIntLT(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); + AssertIntEQ(ASN1_INTEGER_set(a, 0x01), 1); + AssertIntEQ(ASN1_INTEGER_set(b, 0x1000), 1); + AssertIntLT(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); + AssertIntGT(wolfSSL_ASN1_INTEGER_cmp(b, a), 0); + + ASN1_INTEGER_free(b); + ASN1_INTEGER_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_INTEGER_BN(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER* ai; + ASN1_INTEGER* a2; + BIGNUM* a; + + ai = ASN1_INTEGER_new(); + AssertNotNull(ai); + + /* Invalid parameter testing. */ + AssertNull(a = ASN1_INTEGER_to_BN(NULL, NULL)); + AssertNull(a2 = BN_to_ASN1_INTEGER(NULL, NULL)); + + /* at the moment hard setting since no set function */ + ai->data[0] = 0xff; /* No DER encoding. */ + ai->length = 1; +#if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, NULL)); + BN_free(a); +#else + AssertNull(ASN1_INTEGER_to_BN(ai, NULL)); +#endif + + ai->data[0] = 0x02; /* tag for ASN_INTEGER */ + ai->data[1] = 0x04; /* bad length of integer */ + ai->data[2] = 0x03; + ai->length = 3; +#if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) + /* Interpreted as a number 0x020403. */ + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, NULL)); + BN_free(a); +#else + AssertNull(ASN1_INTEGER_to_BN(ai, NULL)); +#endif + + ai->data[0] = 0x02; /* tag for ASN_INTEGER */ + ai->data[1] = 0x01; /* length of integer */ + ai->data[2] = 0x03; + ai->length = 3; + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, NULL)); + AssertNotNull(a2 = BN_to_ASN1_INTEGER(a, NULL)); + AssertIntEQ(ASN1_INTEGER_cmp(ai, a2), 0); + + ai->data[0] = 0x02; /* tag for ASN_INTEGER */ + ai->data[1] = 0x01; /* length of integer */ + ai->data[2] = 0xff; + ai->length = 3; + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, a)); + AssertNotNull(a2 = BN_to_ASN1_INTEGER(a, a2)); + AssertIntEQ(ASN1_INTEGER_cmp(ai, a2), 0); + + ai->data[0] = 0x02; /* tag for ASN_INTEGER */ + ai->data[1] = 0x01; /* length of integer */ + ai->data[2] = 0x00; + ai->length = 3; + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, a)); + AssertNotNull(a2 = BN_to_ASN1_INTEGER(a, a2)); + AssertIntEQ(ASN1_INTEGER_cmp(ai, a2), 0); + + ai->data[0] = 0x02; /* tag for ASN_INTEGER */ + ai->data[1] = 0x01; /* length of integer */ + ai->data[2] = 0x01; + ai->length = 3; + ai->negative = 1; + AssertNotNull(a = ASN1_INTEGER_to_BN(ai, a)); + AssertNotNull(a2 = BN_to_ASN1_INTEGER(a, a2)); + AssertIntEQ(ASN1_INTEGER_cmp(ai, a2), 0); + + BN_free(a); + ASN1_INTEGER_free(a2); + ASN1_INTEGER_free(ai); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_INTEGER_get_set(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER *a; + long val; + int ret; + + a = ASN1_INTEGER_new(); + /* Invalid parameter testing. */ + AssertIntEQ(ASN1_INTEGER_get(NULL), 0); +#if defined(WOLFSSL_QT) || defined(WOLFSSL_HAPROXY) + AssertIntEQ(ASN1_INTEGER_get(a), 0); +#else + AssertIntEQ(ASN1_INTEGER_get(a), -1); +#endif + ASN1_INTEGER_free(a); + + a = ASN1_INTEGER_new(); + val = 0; + ret = ASN1_INTEGER_set(NULL, val); + AssertIntEQ(ret, 0); + ASN1_INTEGER_free(a); + + /* 0 */ + a = ASN1_INTEGER_new(); + val = 0; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* 40 */ + a = ASN1_INTEGER_new(); + val = 40; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* -40 */ + a = ASN1_INTEGER_new(); + val = -40; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* 128 */ + a = ASN1_INTEGER_new(); + val = 128; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* -128 */ + a = ASN1_INTEGER_new(); + val = -128; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* 200 */ + a = ASN1_INTEGER_new(); + val = 200; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* int max (2147483647) */ + a = ASN1_INTEGER_new(); + val = 2147483647; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* int min (-2147483648) */ + a = ASN1_INTEGER_new(); + val = -2147483647 - 1; + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + /* long max positive */ + a = ASN1_INTEGER_new(); + val = (long)(((unsigned long)-1) >> 1); + ret = ASN1_INTEGER_set(a, val); + AssertIntEQ(ret, 1); + AssertIntEQ(ASN1_INTEGER_get(a), val); + ASN1_INTEGER_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +#if defined(OPENSSL_EXTRA) +typedef struct ASN1IntTestVector { + const byte* der; + const size_t derSz; + const long value; +} ASN1IntTestVector; +#endif +static int test_wolfSSL_d2i_ASN1_INTEGER(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) + size_t i; + WOLFSSL_ASN1_INTEGER* a = NULL; + WOLFSSL_ASN1_INTEGER* b = NULL; + WOLFSSL_ASN1_INTEGER* c = NULL; + const byte* p = NULL; + byte* reEncoded = NULL; + int reEncodedSz; + + static const byte zeroDer[] = { + 0x02, 0x01, 0x00 + }; + static const byte oneDer[] = { + 0x02, 0x01, 0x01 + }; + static const byte negativeDer[] = { + 0x02, 0x03, 0xC1, 0x16, 0x0D + }; + static const byte positiveDer[] = { + 0x02, 0x03, 0x01, 0x00, 0x01 + }; + static const byte primeDer[] = { + 0x02, 0x82, 0x01, 0x01, 0x00, 0xc0, 0x95, 0x08, 0xe1, 0x57, 0x41, + 0xf2, 0x71, 0x6d, 0xb7, 0xd2, 0x45, 0x41, 0x27, 0x01, 0x65, 0xc6, + 0x45, 0xae, 0xf2, 0xbc, 0x24, 0x30, 0xb8, 0x95, 0xce, 0x2f, 0x4e, + 0xd6, 0xf6, 0x1c, 0x88, 0xbc, 0x7c, 0x9f, 0xfb, 0xa8, 0x67, 0x7f, + 0xfe, 0x5c, 0x9c, 0x51, 0x75, 0xf7, 0x8a, 0xca, 0x07, 0xe7, 0x35, + 0x2f, 0x8f, 0xe1, 0xbd, 0x7b, 0xc0, 0x2f, 0x7c, 0xab, 0x64, 0xa8, + 0x17, 0xfc, 0xca, 0x5d, 0x7b, 0xba, 0xe0, 0x21, 0xe5, 0x72, 0x2e, + 0x6f, 0x2e, 0x86, 0xd8, 0x95, 0x73, 0xda, 0xac, 0x1b, 0x53, 0xb9, + 0x5f, 0x3f, 0xd7, 0x19, 0x0d, 0x25, 0x4f, 0xe1, 0x63, 0x63, 0x51, + 0x8b, 0x0b, 0x64, 0x3f, 0xad, 0x43, 0xb8, 0xa5, 0x1c, 0x5c, 0x34, + 0xb3, 0xae, 0x00, 0xa0, 0x63, 0xc5, 0xf6, 0x7f, 0x0b, 0x59, 0x68, + 0x78, 0x73, 0xa6, 0x8c, 0x18, 0xa9, 0x02, 0x6d, 0xaf, 0xc3, 0x19, + 0x01, 0x2e, 0xb8, 0x10, 0xe3, 0xc6, 0xcc, 0x40, 0xb4, 0x69, 0xa3, + 0x46, 0x33, 0x69, 0x87, 0x6e, 0xc4, 0xbb, 0x17, 0xa6, 0xf3, 0xe8, + 0xdd, 0xad, 0x73, 0xbc, 0x7b, 0x2f, 0x21, 0xb5, 0xfd, 0x66, 0x51, + 0x0c, 0xbd, 0x54, 0xb3, 0xe1, 0x6d, 0x5f, 0x1c, 0xbc, 0x23, 0x73, + 0xd1, 0x09, 0x03, 0x89, 0x14, 0xd2, 0x10, 0xb9, 0x64, 0xc3, 0x2a, + 0xd0, 0xa1, 0x96, 0x4a, 0xbc, 0xe1, 0xd4, 0x1a, 0x5b, 0xc7, 0xa0, + 0xc0, 0xc1, 0x63, 0x78, 0x0f, 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, + 0x32, 0x23, 0x95, 0xa1, 0x77, 0xba, 0x13, 0xd2, 0x97, 0x73, 0xe2, + 0x5d, 0x25, 0xc9, 0x6a, 0x0d, 0xc3, 0x39, 0x60, 0xa4, 0xb4, 0xb0, + 0x69, 0x42, 0x42, 0x09, 0xe9, 0xd8, 0x08, 0xbc, 0x33, 0x20, 0xb3, + 0x58, 0x22, 0xa7, 0xaa, 0xeb, 0xc4, 0xe1, 0xe6, 0x61, 0x83, 0xc5, + 0xd2, 0x96, 0xdf, 0xd9, 0xd0, 0x4f, 0xad, 0xd7 + }; + static const byte garbageDer[] = {0xDE, 0xAD, 0xBE, 0xEF}; + + static const ASN1IntTestVector testVectors[] = { + {zeroDer, sizeof(zeroDer), 0}, + {oneDer, sizeof(oneDer), 1}, + {negativeDer, sizeof(negativeDer), -4123123}, + {positiveDer, sizeof(positiveDer), 65537}, + {primeDer, sizeof(primeDer), 0} + }; + static const size_t NUM_TEST_VECTORS = sizeof(testVectors)/sizeof(testVectors[0]); + + /* Check d2i error conditions */ + /* NULL pointer to input. */ + AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, NULL, 1))); + AssertNull(b); + /* NULL input. */ + AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, 1))); + AssertNull(b); + /* 0 length. */ + p = testVectors[0].der; + AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, 0))); + AssertNull(b); + /* Negative length. */ + p = testVectors[0].der; + AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, -1))); + AssertNull(b); + /* Garbage DER input. */ + p = garbageDer; + AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, sizeof(garbageDer)))); + AssertNull(b); + + { + /* Check i2d error conditions */ + /* NULL input. */ + byte* p2 = NULL; + AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(NULL, &p2), 0); + /* 0 length input data buffer (a->length == 0). */ + AssertNotNull((a = wolfSSL_ASN1_INTEGER_new())); + AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(a, &p2), 0); + a->data = NULL; + /* NULL input data buffer. */ + AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(a, &p2), 0); + /* Reset a->data. */ + a->data = a->intData; + /* Set a to valid value. */ + AssertIntEQ(wolfSSL_ASN1_INTEGER_set(a, 1), WOLFSSL_SUCCESS); + /* NULL output buffer. */ + AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(a, NULL), 0); + wolfSSL_ASN1_INTEGER_free(a); + } + + for (i = 0; i < NUM_TEST_VECTORS; ++i) { + p = testVectors[i].der; + a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, testVectors[i].derSz); + AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); + + if (testVectors[i].derSz <= sizeof(long)) { + c = wolfSSL_ASN1_INTEGER_new(); + wolfSSL_ASN1_INTEGER_set(c, testVectors[i].value); + AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, c), 0); + wolfSSL_ASN1_INTEGER_free(c); + } + + /* Convert to DER without a pre-allocated output buffer. */ + AssertIntGT((reEncodedSz = wolfSSL_i2d_ASN1_INTEGER(a, &reEncoded)), 0); + AssertIntEQ(reEncodedSz, testVectors[i].derSz); + AssertIntEQ(XMEMCMP(reEncoded, testVectors[i].der, reEncodedSz), 0); + + /* Convert to DER with a pre-allocated output buffer. In this case, the + * output buffer pointer should be incremented just past the end of the + * encoded data. */ + p = reEncoded; + AssertIntGT((reEncodedSz = wolfSSL_i2d_ASN1_INTEGER(a, &reEncoded)), 0); + AssertIntEQ(reEncodedSz, testVectors[i].derSz); + AssertPtrEq(p, reEncoded - reEncodedSz); + AssertIntEQ(XMEMCMP(p, testVectors[i].der, reEncodedSz), 0); + + XFREE(reEncoded - reEncodedSz, NULL, DYNAMIC_TYPE_ASN1); + reEncoded = NULL; + wolfSSL_ASN1_INTEGER_free(a); + } + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA */ + return res; +} + +static int test_wolfSSL_a2i_ASN1_INTEGER(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) + BIO* bio; + BIO* out; + BIO* fixed; + ASN1_INTEGER* ai; + char buf[] = "123456\n12345\n1123456789123456\\\n78901234567890 \r\n\n"; + char tmp[1024]; + int tmpSz; + + const char expected1[] = "123456"; + const char expected2[] = "112345678912345678901234567890"; + char longStr[] = "123456781234567812345678123456781234567812345678\n" + "123456781234567812345678123456781234567812345678\\\n12345678\n"; + + AssertNotNull(out = BIO_new(BIO_s_mem())); + AssertNotNull(ai = ASN1_INTEGER_new()); + + AssertNotNull(bio = BIO_new_mem_buf(buf, -1)); + + /* Invalid parameter testing. */ + AssertIntEQ(a2i_ASN1_INTEGER(NULL, NULL, NULL, -1), 0); + AssertIntEQ(a2i_ASN1_INTEGER(bio, NULL, NULL, -1), 0); + AssertIntEQ(a2i_ASN1_INTEGER(NULL, ai, NULL, -1), 0); + AssertIntEQ(a2i_ASN1_INTEGER(NULL, NULL, tmp, -1), 0); + AssertIntEQ(a2i_ASN1_INTEGER(NULL, NULL, NULL, 1024), 0); + AssertIntEQ(a2i_ASN1_INTEGER(NULL, ai, tmp, 1024), 0); + AssertIntEQ(a2i_ASN1_INTEGER(bio, NULL, tmp, 1024), 0); + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, NULL, 1024), 0); + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, -1), 0); + AssertIntEQ(i2a_ASN1_INTEGER(NULL, NULL), 0); + AssertIntEQ(i2a_ASN1_INTEGER(bio, NULL), 0); + AssertIntEQ(i2a_ASN1_INTEGER(NULL, ai), 0); + + /* No data to read from BIO. */ + AssertIntEQ(a2i_ASN1_INTEGER(out, ai, tmp, 1024), 0); + + /* read first line */ + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), 1); + AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 6); + XMEMSET(tmp, 0, 1024); + tmpSz = BIO_read(out, tmp, 1024); + AssertIntEQ(tmpSz, 6); + AssertIntEQ(XMEMCMP(tmp, expected1, tmpSz), 0); + + /* fail on second line (not % 2) */ + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), 0); + + /* read 3rd long line */ + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), 1); + AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 30); + XMEMSET(tmp, 0, 1024); + tmpSz = BIO_read(out, tmp, 1024); + AssertIntEQ(tmpSz, 30); + AssertIntEQ(XMEMCMP(tmp, expected2, tmpSz), 0); + + /* fail on empty line */ + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), 0); + + BIO_free(bio); + + /* Make long integer, requiring dynamic memory, even longer. */ + AssertNotNull(bio = BIO_new_mem_buf(longStr, -1)); + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), 1); + AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 48); + XMEMSET(tmp, 0, 1024); + tmpSz = BIO_read(out, tmp, 1024); + AssertIntEQ(tmpSz, 48); + AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), 1); + AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 56); + XMEMSET(tmp, 0, 1024); + tmpSz = BIO_read(out, tmp, 1024); + AssertIntEQ(tmpSz, 56); + AssertIntEQ(wolfSSL_ASN1_INTEGER_set(ai, 1), 1); + BIO_free(bio); + BIO_free(out); + + AssertNotNull(fixed = BIO_new(wolfSSL_BIO_s_fixed_mem())); + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(i2a_ASN1_INTEGER(fixed, ai), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(i2a_ASN1_INTEGER(fixed, ai), 0); + BIO_free(fixed); + + ASN1_INTEGER_free(ai); + + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_i2c_ASN1_INTEGER(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + ASN1_INTEGER *a; + unsigned char *pp,*tpp; + int ret; + + a = wolfSSL_ASN1_INTEGER_new(); + + /* Invalid parameter testing. */ + /* Set pp to an invalid value. */ + pp = NULL; + AssertIntEQ(i2c_ASN1_INTEGER(NULL, &pp), 0); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 0); + AssertIntEQ(i2c_ASN1_INTEGER(NULL, NULL), 0); + + /* 40 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 40; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 1); + pp--; + AssertIntEQ(*pp, 40); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* 128 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 128; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 2); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 2); + pp--; + AssertIntEQ(*(pp--), 128); + AssertIntEQ(*pp, 0); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -40 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 40; + a->negative = 1; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 1); + pp--; + AssertIntEQ(*pp, 216); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -128 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 128; + a->negative = 1; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 1); + pp--; + AssertIntEQ(*pp, 128); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -200 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 200; + a->negative = 1; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 2); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 2); + pp--; + AssertIntEQ(*(pp--), 56); + AssertIntEQ(*pp, 255); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* Empty */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 0; + a->negative = 0; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 1); + pp--; + AssertIntEQ(*pp, 0); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* 0 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 1; + a->intData[2] = 0; + a->negative = 1; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 1); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 1); + pp--; + AssertIntEQ(*pp, 0); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* 0x100 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 2; + a->intData[2] = 0x01; + a->intData[3] = 0x00; + a->negative = 0; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 2); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 2); + pp -= 2; + AssertIntEQ(pp[0], 0x01); + AssertIntEQ(pp[1], 0x00); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -0x8000 => 0x8000 */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 2; + a->intData[2] = 0x80; + a->intData[3] = 0x00; + a->negative = 1; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 2); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 2); + pp -= 2; + AssertIntEQ(pp[0], 0x80); + AssertIntEQ(pp[1], 0x00); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* -0x8001 => 0xFF7FFF */ + a->intData[0] = ASN_INTEGER; + a->intData[1] = 2; + a->intData[2] = 0x80; + a->intData[3] = 0x01; + a->negative = 1; + AssertIntEQ(ret = i2c_ASN1_INTEGER(a, NULL), 3); + AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + tpp = pp; + XMEMSET(pp, 0, ret + 1); + AssertIntEQ(i2c_ASN1_INTEGER(a, &pp), 3); + pp -= 3; + AssertIntEQ(pp[0], 0xFF); + AssertIntEQ(pp[1], 0x7F); + AssertIntEQ(pp[2], 0xFF); + XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + wolfSSL_ASN1_INTEGER_free(a); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && !NO_ASN */ + return res; +} + +static int test_wolfSSL_ASN1_OBJECT(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) + ASN1_OBJECT* a; + ASN1_OBJECT s; + const unsigned char der[] = { 0x06, 0x01, 0x00 }; + + /* Invalid parameter testing. */ + ASN1_OBJECT_free(NULL); + AssertNull(wolfSSL_ASN1_OBJECT_dup(NULL)); + + /* Test that a static ASN1_OBJECT can be freed. */ + XMEMSET(&s, 0, sizeof(ASN1_OBJECT)); + ASN1_OBJECT_free(&s); + AssertNotNull(a = wolfSSL_ASN1_OBJECT_dup(&s)); + ASN1_OBJECT_free(a); + s.obj = der; + AssertNotNull(a = wolfSSL_ASN1_OBJECT_dup(&s)); + ASN1_OBJECT_free(a); + ASN1_OBJECT_free(&s); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA */ + return res; +} + +static int test_wolfSSL_ASN1_get_object(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + const unsigned char* derBuf = cliecc_cert_der_256; + const unsigned char* nullPtr = NULL; + const unsigned char objDerInvalidLen[] = { 0x30, 0x81 }; + const unsigned char objDerBadLen[] = { 0x30, 0x04 }; + const unsigned char objDerNotObj[] = { 0x02, 0x01, 0x00 }; + const unsigned char objDerNoData[] = { 0x06, 0x00 }; + const unsigned char* p; + unsigned char objDer[8]; + unsigned char* der; + unsigned char* derPtr; + int len = sizeof_cliecc_cert_der_256; + long asnLen = 0; + int tag = 0; + int cls = 0; + ASN1_OBJECT* a; + ASN1_OBJECT s; + + XMEMSET(&s, 0, sizeof(ASN1_OBJECT)); + + /* Invalid encoding at length. */ + p = objDerInvalidLen; + AssertIntEQ(ASN1_get_object(&p, &asnLen, &tag, &cls, sizeof(objDerBadLen)), + 0x80); + p = objDerBadLen; + /* Error = 0x80, Constructed = 0x20 */ + AssertIntEQ(ASN1_get_object(&p, &asnLen, &tag, &cls, sizeof(objDerBadLen)), + 0x80 | 0x20); + + /* Read a couple TLV triplets and make sure they match the expected values + */ + + /* SEQUENCE */ + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, len) & 0x80, 0); + AssertIntEQ(asnLen, 862); + AssertIntEQ(tag, 0x10); + AssertIntEQ(cls, 0); + + /* SEQUENCE */ + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, + len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); + AssertIntEQ(asnLen, 772); + AssertIntEQ(tag, 0x10); + AssertIntEQ(cls, 0); + + /* [0] */ + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, + len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); + AssertIntEQ(asnLen, 3); + AssertIntEQ(tag, 0); + AssertIntEQ(cls, 0x80); + + /* INTEGER */ + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, + len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); + AssertIntEQ(asnLen, 1); + AssertIntEQ(tag, 0x2); + AssertIntEQ(cls, 0); + derBuf += asnLen; + + /* INTEGER */ + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, + len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); + AssertIntEQ(asnLen, 20); + AssertIntEQ(tag, 0x2); + AssertIntEQ(cls, 0); + derBuf += asnLen; + + /* SEQUENCE */ + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, + len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); + AssertIntEQ(asnLen, 10); + AssertIntEQ(tag, 0x10); + AssertIntEQ(cls, 0); + + /* Found OBJECT_ID. */ + + /* Invalid parameter testing. */ + AssertIntEQ(ASN1_get_object(NULL, NULL, NULL, NULL, 0), 0x80); + AssertIntEQ(ASN1_get_object(&nullPtr, NULL, NULL, NULL, 0), 0x80); + AssertIntEQ(ASN1_get_object(NULL, &asnLen, &tag, &cls, len), 0x80); + AssertIntEQ(ASN1_get_object(&nullPtr, &asnLen, &tag, &cls, len), 0x80); + AssertIntEQ(ASN1_get_object(&derBuf, NULL, &tag, &cls, len), 0x80); + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, NULL, &cls, len), 0x80); + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, NULL, len), 0x80); + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, 0), 0x80); + AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, -1), 0x80); + AssertNull(d2i_ASN1_OBJECT(NULL, NULL, -1)); + AssertNull(d2i_ASN1_OBJECT(NULL, &nullPtr, -1)); + AssertNull(d2i_ASN1_OBJECT(NULL, &derBuf, -1)); + AssertNull(d2i_ASN1_OBJECT(NULL, NULL, 0)); + AssertNull(d2i_ASN1_OBJECT(&a, NULL, len)); + AssertNull(d2i_ASN1_OBJECT(&a, &nullPtr, len)); + AssertNull(d2i_ASN1_OBJECT(&a, &derBuf, -1)); + AssertNull(c2i_ASN1_OBJECT(NULL, NULL, -1)); + AssertNull(c2i_ASN1_OBJECT(NULL, &nullPtr, -1)); + AssertNull(c2i_ASN1_OBJECT(NULL, &derBuf, -1)); + AssertNull(c2i_ASN1_OBJECT(NULL, NULL, 1)); + AssertNull(c2i_ASN1_OBJECT(NULL, &nullPtr, 1)); + + /* Invalid encoding at length. */ + p = objDerInvalidLen; + AssertNull(d2i_ASN1_OBJECT(&a, &p, sizeof(objDerInvalidLen))); + p = objDerBadLen; + AssertNull(d2i_ASN1_OBJECT(&a, &p, sizeof(objDerBadLen))); + p = objDerNotObj; + AssertNull(d2i_ASN1_OBJECT(&a, &p, sizeof(objDerNotObj))); + p = objDerNoData; + AssertNull(d2i_ASN1_OBJECT(&a, &p, sizeof(objDerNoData))); + + /* Create an ASN OBJECT from content */ + p = derBuf + 2; + AssertNotNull(a = c2i_ASN1_OBJECT(NULL, &p, 8)); + ASN1_OBJECT_free(a); + /* Create an ASN OBJECT from DER */ + AssertNotNull(d2i_ASN1_OBJECT(&a, &derBuf, len)); + + /* Invalid parameter testing. */ + AssertIntEQ(i2d_ASN1_OBJECT(NULL, NULL), 0); + AssertIntEQ(i2d_ASN1_OBJECT(&s, NULL), 0); + + AssertIntEQ(i2d_ASN1_OBJECT(a, NULL), 8); + der = NULL; + AssertIntEQ(i2d_ASN1_OBJECT(a, &der), 8); + derPtr = objDer; + AssertIntEQ(i2d_ASN1_OBJECT(a, &derPtr), 8); + AssertPtrNE(derPtr, objDer); + AssertIntEQ(XMEMCMP(der, objDer, 8), 0); + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + + ASN1_OBJECT_free(a); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && HAVE_ECC && USE_CERT_BUFFERS_256 */ + return res; +} + +static int test_wolfSSL_i2a_ASN1_OBJECT(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(NO_BIO) + ASN1_OBJECT* obj = NULL; + ASN1_OBJECT* a = NULL; + BIO *bio = NULL; + const unsigned char notObjDer[] = { 0x04, 0x01, 0xff }; + const unsigned char badLenDer[] = { 0x06, 0x04, 0x01 }; + const unsigned char goodDer[] = { 0x06, 0x01, 0x01 }; + const unsigned char* p; + + AssertNotNull(obj = OBJ_nid2obj(NID_sha256)); + AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); + + AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, obj), 0); + AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, NULL), 0); + + AssertIntEQ(wolfSSL_i2a_ASN1_OBJECT(NULL, obj), 0); + + /* No DER encoding in ASN1_OBJECT. */ + a = wolfSSL_ASN1_OBJECT_new(); + AssertIntEQ(wolfSSL_i2a_ASN1_OBJECT(bio, a), 0); + ASN1_OBJECT_free(a); + /* DER encoding - not OBJECT_ID */ + p = notObjDer; + AssertNotNull(a = c2i_ASN1_OBJECT(NULL, &p, 3)); + AssertIntEQ(wolfSSL_i2a_ASN1_OBJECT(bio, a), 0); + ASN1_OBJECT_free(a); + /* Bad length encoding. */ + p = badLenDer; + AssertNotNull(a = c2i_ASN1_OBJECT(NULL, &p, 3)); + AssertIntEQ(wolfSSL_i2a_ASN1_OBJECT(bio, a), 0); + ASN1_OBJECT_free(a); + /* Good encoding - but unknown. */ + p = goodDer; + AssertNotNull(a = c2i_ASN1_OBJECT(NULL, &p, 3)); + AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, a), 0); + ASN1_OBJECT_free(a); + + BIO_free(bio); + ASN1_OBJECT_free(obj); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_i2t_ASN1_OBJECT(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) + + char buf[50] = {0}; + ASN1_OBJECT* obj; + const char* oid = "2.5.29.19"; + const char* ln = "X509v3 Basic Constraints"; + + obj = NULL; + AssertIntEQ(i2t_ASN1_OBJECT(NULL, sizeof(buf), obj), 0); + AssertIntEQ(i2t_ASN1_OBJECT(buf, sizeof(buf), NULL), 0); + AssertIntEQ(i2t_ASN1_OBJECT(buf, 0, NULL), 0); + + AssertNotNull(obj = OBJ_txt2obj(oid, 0)); + XMEMSET(buf, 0, sizeof(buf)); + AssertIntEQ(i2t_ASN1_OBJECT(buf, sizeof(buf), obj), XSTRLEN(ln)); + AssertIntEQ(XSTRNCMP(buf, ln, XSTRLEN(ln)), 0); + ASN1_OBJECT_free(obj); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && WOLFSSL_CERT_EXT && WOLFSSL_CERT_GEN */ + return res; +} + +static int test_wolfSSL_sk_ASN1_OBJECT(void) +{ + int res = TEST_SKIPPED; +#if !defined(NO_ASN) && (defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)) + WOLFSSL_STACK* sk; + WOLFSSL_ASN1_OBJECT* obj; + + AssertNotNull(obj = wolfSSL_ASN1_OBJECT_new()); + + AssertNotNull(sk = wolfSSL_sk_new_asn1_obj()); + wolfSSL_sk_ASN1_OBJECT_free(sk); + + AssertNotNull(sk = wolfSSL_sk_new_asn1_obj()); + AssertIntEQ(wolfSSL_sk_ASN1_OBJECT_push(NULL, NULL), 0); + AssertIntEQ(wolfSSL_sk_ASN1_OBJECT_push(sk, NULL), 0); + AssertIntEQ(wolfSSL_sk_ASN1_OBJECT_push(NULL, obj), 0); + AssertIntEQ(wolfSSL_sk_ASN1_OBJECT_push(sk, obj), 1); + wolfSSL_sk_ASN1_OBJECT_pop_free(sk, NULL); + /* obj freed in pop_free call. */ + + AssertNotNull(obj = wolfSSL_ASN1_OBJECT_new()); + AssertNotNull(sk = wolfSSL_sk_new_asn1_obj()); + AssertIntEQ(wolfSSL_sk_ASN1_OBJECT_push(sk, obj), 1); + AssertPtrEq(obj, wolfSSL_sk_ASN1_OBJECT_pop(sk)); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_ASN1_OBJECT_free(obj); + + res = TEST_RES_CHECK(1); +#endif /* !NO_ASN && (OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL) */ + return res; +} + +static int test_wolfSSL_ASN1_STRING(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) + ASN1_STRING* str = NULL; + ASN1_STRING* c = NULL; + const char data[] = "hello wolfSSL"; + const char data2[] = "Same len data"; + const char longData[] = + "This string must be longer than CTC_NAME_SIZE that is defined as 64."; + + AssertNotNull(str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); + ASN1_STRING_free(str); + + AssertNotNull(str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); + AssertIntEQ(ASN1_STRING_type(str), V_ASN1_OCTET_STRING); + AssertIntEQ(ASN1_STRING_type(NULL), 0); + /* Check setting to NULL works. */ + AssertIntEQ(ASN1_STRING_set(str, NULL, 0), 1); + AssertIntEQ(ASN1_STRING_set(str, (const void*)data, sizeof(data)), 1); + AssertIntEQ(ASN1_STRING_set(str, (const void*)data, -1), 1); + AssertIntEQ(ASN1_STRING_set(str, NULL, -1), 0); + AssertIntEQ(ASN1_STRING_set(NULL, NULL, 0), 0); + + AssertIntEQ(wolfSSL_ASN1_STRING_copy(NULL, NULL), 0); + AssertIntEQ(wolfSSL_ASN1_STRING_copy(str, NULL), 0); + AssertIntEQ(wolfSSL_ASN1_STRING_copy(NULL, str), 0); + AssertNull(wolfSSL_ASN1_STRING_dup(NULL)); + + AssertNotNull(c = wolfSSL_ASN1_STRING_dup(str)); + AssertIntEQ(ASN1_STRING_cmp(NULL, NULL), -1); + AssertIntEQ(ASN1_STRING_cmp(str, NULL), -1); + AssertIntEQ(ASN1_STRING_cmp(NULL, c), -1); + AssertIntEQ(ASN1_STRING_cmp(str, c), 0); + AssertIntEQ(ASN1_STRING_set(c, (const void*)data2, -1), 1); + AssertIntGT(ASN1_STRING_cmp(str, c), 0); + AssertIntEQ(ASN1_STRING_set(str, (const void*)longData, -1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_copy(c, str), 1); + AssertIntEQ(ASN1_STRING_cmp(str, c), 0); + /* Check setting back to smaller size frees dynamic data. */ + AssertIntEQ(ASN1_STRING_set(str, (const void*)data, -1), 1); + AssertIntLT(ASN1_STRING_cmp(str, c), 0); + AssertIntGT(ASN1_STRING_cmp(c, str), 0); + + AssertNull(ASN1_STRING_get0_data(NULL)); + AssertNotNull(ASN1_STRING_get0_data(str)); + AssertNull(ASN1_STRING_data(NULL)); + AssertNotNull(ASN1_STRING_data(str)); + AssertIntEQ(ASN1_STRING_length(NULL), 0); + AssertIntGT(ASN1_STRING_length(str), 0); + + ASN1_STRING_free(c); + ASN1_STRING_free(str); + ASN1_STRING_free(NULL); + +#ifndef NO_WOLFSSL_STUB + AssertNull(d2i_DISPLAYTEXT(NULL, NULL, 0)); +#endif + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_STRING_to_UTF8(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_ALL) && !defined(NO_ASN) && !defined(NO_RSA) + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* subject; + WOLFSSL_X509_NAME_ENTRY* e; + WOLFSSL_ASN1_STRING* a; + FILE* file; + int idx = 0; + char targetOutput[16] = "www.wolfssl.com"; + unsigned char* actual_output; + int len = 0; + int result = 0; + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + + /* wolfSSL_ASN1_STRING_to_UTF8(): NID_commonName */ + AssertNotNull(subject = wolfSSL_X509_get_subject_name(x509)); + AssertIntEQ((idx = wolfSSL_X509_NAME_get_index_by_NID(subject, + NID_commonName, -1)), 5); + AssertNotNull(e = wolfSSL_X509_NAME_get_entry(subject, idx)); + AssertNotNull(a = wolfSSL_X509_NAME_ENTRY_get_data(e)); + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(&actual_output, a)), 15); + result = strncmp((const char*)actual_output, targetOutput, len); + AssertIntEQ(result, 0); + + /* wolfSSL_ASN1_STRING_to_UTF8(NULL, valid) */ + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(NULL, a)), -1); + + /* wolfSSL_ASN1_STRING_to_UTF8(valid, NULL) */ + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(&actual_output, NULL)), -1); + + /* wolfSSL_ASN1_STRING_to_UTF8(NULL, NULL) */ + AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(NULL, NULL)), -1); + + wolfSSL_X509_free(x509); + XFREE(actual_output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + AssertNotNull(a = ASN1_STRING_new()); + AssertIntEQ(wolfSSL_ASN1_STRING_to_UTF8(&actual_output, a), -1); + ASN1_STRING_free(a); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_i2s_ASN1_STRING(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + WOLFSSL_ASN1_STRING* str; + const char* data = "test_wolfSSL_i2s_ASN1_STRING"; + char* ret; + + AssertNotNull(str = ASN1_STRING_new()); + + AssertNull(wolfSSL_i2s_ASN1_STRING(NULL, NULL)); + /* No data. */ + AssertNull(wolfSSL_i2s_ASN1_STRING(NULL, str)); + + AssertIntEQ(ASN1_STRING_set(str, data, 0), 1); + AssertNotNull(ret = wolfSSL_i2s_ASN1_STRING(NULL, str)); + XFREE(ret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + AssertIntEQ(ASN1_STRING_set(str, data, -1), 1); + /* No type. */ + AssertNotNull(ret = wolfSSL_i2s_ASN1_STRING(NULL, str)); + XFREE(ret, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + ASN1_STRING_free(str); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_STRING_canon(void) +{ + int res = TEST_SKIPPED; +#if defined(WOLFSSL_TEST_STATIC_BUILD) +#if !defined(NO_CERTS) && (defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_ASN1_STRING* orig; + WOLFSSL_ASN1_STRING* canon; + const char* data = "test_wolfSSL_ASN1_STRING_canon"; + const char* whitespaceOnly = "\t\r\n"; + const char* modData = " \x01\f\t\x02\r\n\v\xff\nTt \n"; + const char* canonData = "\x01 \x02 \xff tt"; + const char longData[] = + "This string must be longer than CTC_NAME_SIZE that is defined as 64."; + + AssertNotNull(orig = ASN1_STRING_new()); + AssertNotNull(canon = ASN1_STRING_new()); + + /* Invalid parameter testing. */ + AssertIntEQ(wolfSSL_ASN1_STRING_canon(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_ASN1_STRING_canon(canon, NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_ASN1_STRING_canon(NULL, orig), BAD_FUNC_ARG); + + AssertIntEQ(wolfSSL_ASN1_STRING_canon(canon, orig), 1); + AssertIntEQ(ASN1_STRING_cmp(orig, canon), 0); + + AssertIntEQ(ASN1_STRING_set(orig, longData, (int)XSTRLEN(data)), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_canon(canon, orig), 1); + AssertIntEQ(ASN1_STRING_cmp(orig, canon), 0); + + AssertIntEQ(ASN1_STRING_set(orig, data, (int)XSTRLEN(data)), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_canon(canon, orig), 1); + AssertIntEQ(ASN1_STRING_cmp(orig, canon), 0); + + ASN1_STRING_free(orig); + + AssertNotNull(orig = ASN1_STRING_type_new(MBSTRING_UTF8)); + AssertIntEQ(ASN1_STRING_set(orig, modData, 15), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_canon(canon, orig), 1); + AssertIntEQ(ASN1_STRING_set(orig, canonData, 8), 1); + AssertIntEQ(ASN1_STRING_cmp(orig, canon), 0); + ASN1_STRING_free(orig); + + AssertNotNull(orig = ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)); + AssertIntEQ(ASN1_STRING_set(orig, whitespaceOnly, 3), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_canon(canon, orig), 1); + ASN1_STRING_free(orig); + AssertNotNull(orig = ASN1_STRING_type_new(MBSTRING_UTF8)); + AssertIntEQ(ASN1_STRING_cmp(orig, canon), 0); + + ASN1_STRING_free(orig); + ASN1_STRING_free(canon); + + res = TEST_RES_CHECK(1); +#endif +#endif + return res; +} + +static int test_wolfSSL_ASN1_STRING_print(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_ALL) && !defined(NO_ASN) && !defined(NO_CERTS) && \ + !defined(NO_BIO) + ASN1_STRING* asnStr = NULL; + const char HELLO_DATA[]= \ + {'H','e','l','l','o',' ','w','o','l','f','S','S','L','!'}; + #define MAX_UNPRINTABLE_CHAR 32 + #define MAX_BUF 255 + unsigned char unprintableData[MAX_UNPRINTABLE_CHAR + sizeof(HELLO_DATA)]; + unsigned char expected[sizeof(unprintableData)+1]; + unsigned char rbuf[MAX_BUF]; + + BIO *bio; + int p_len, i; + + /* setup */ + + for (i = 0; i < (int)sizeof(HELLO_DATA); i++) { + unprintableData[i] = HELLO_DATA[i]; + expected[i] = HELLO_DATA[i]; + } + + for (i = 0; i < (int)MAX_UNPRINTABLE_CHAR; i++) { + unprintableData[sizeof(HELLO_DATA)+i] = i; + + if (i == (int)'\n' || i == (int)'\r') + expected[sizeof(HELLO_DATA)+i] = i; + else + expected[sizeof(HELLO_DATA)+i] = '.'; + } + + unprintableData[sizeof(unprintableData)-1] = '\0'; + expected[sizeof(expected)-1] = '\0'; + + XMEMSET(rbuf, 0, MAX_BUF); + bio = BIO_new(BIO_s_mem()); + BIO_set_write_buf_size(bio, MAX_BUF); + + asnStr = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + ASN1_STRING_set(asnStr,(const void*)unprintableData, + (int)sizeof(unprintableData)); + /* test */ + AssertIntEQ(wolfSSL_ASN1_STRING_print(NULL, NULL), 0); + AssertIntEQ(wolfSSL_ASN1_STRING_print(bio, NULL), 0); + AssertIntEQ(wolfSSL_ASN1_STRING_print(NULL, asnStr), 0); + AssertIntEQ(p_len = wolfSSL_ASN1_STRING_print(bio, asnStr), 46); + BIO_read(bio, (void*)rbuf, 46); + + AssertStrEQ((char*)rbuf, (const char*)expected); + + BIO_free(bio); + + AssertNotNull(bio = BIO_new(wolfSSL_BIO_s_fixed_mem())); + AssertIntEQ(BIO_set_write_buf_size(bio, 0), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print(bio, asnStr), 0); + AssertIntEQ(BIO_set_write_buf_size(bio, 1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print(bio, asnStr), 0); + AssertIntEQ(BIO_set_write_buf_size(bio, 45), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print(bio, asnStr), 0); + BIO_free(bio); + + ASN1_STRING_free(asnStr); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && !NO_ASN && !NO_CERTS && !NO_BIO */ + return res; +} + +static int test_wolfSSL_ASN1_STRING_print_ex(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(NO_BIO) + ASN1_STRING* asn_str; + const char data[] = "Hello wolfSSL!"; + ASN1_STRING* esc_str; + const char esc_data[] = "a+;<>"; + ASN1_STRING* neg_int; + const char neg_int_data[] = "\xff"; + ASN1_STRING* neg_enum; + const char neg_enum_data[] = "\xff"; + BIO *bio; + BIO *fixed; + unsigned long flags; + int p_len; + unsigned char rbuf[255]; + + /* setup */ + XMEMSET(rbuf, 0, 255); + AssertNotNull(bio = BIO_new(BIO_s_mem())); + BIO_set_write_buf_size(bio, 255); + AssertNotNull(fixed = BIO_new(wolfSSL_BIO_s_fixed_mem())); + + asn_str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + ASN1_STRING_set(asn_str, (const void*)data, sizeof(data)); + esc_str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); + ASN1_STRING_set(esc_str, (const void*)esc_data, sizeof(esc_data)); + neg_int = ASN1_STRING_type_new(V_ASN1_NEG_INTEGER); + ASN1_STRING_set(neg_int, (const void*)neg_int_data, + sizeof(neg_int_data) - 1); + neg_enum = ASN1_STRING_type_new(V_ASN1_NEG_ENUMERATED); + ASN1_STRING_set(neg_enum, (const void*)neg_enum_data, + sizeof(neg_enum_data) - 1); + + /* Invalid parameter testing. */ + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(NULL, NULL, 0), 0); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(bio, NULL, 0), 0); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(NULL, asn_str, 0), 0); + + /* no flags */ + XMEMSET(rbuf, 0, 255); + flags = 0; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 15); + BIO_read(bio, (void*)rbuf, 15); + AssertStrEQ((char*)rbuf, "Hello wolfSSL!"); + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 14), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + + /* RFC2253 Escape */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_ESC_2253; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, esc_str, flags); + AssertIntEQ(p_len, 9); + BIO_read(bio, (void*)rbuf, 9); + AssertStrEQ((char*)rbuf, "a\\+\\;\\<\\>"); + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, esc_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, esc_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 8), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, esc_str, flags), 0); + + /* Show type */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_SHOW_TYPE; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 28); + BIO_read(bio, (void*)rbuf, 28); + AssertStrEQ((char*)rbuf, "OCTET STRING:Hello wolfSSL!"); + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 12), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 27), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + + /* Dump All */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 31); + BIO_read(bio, (void*)rbuf, 31); + AssertStrEQ((char*)rbuf, "#48656C6C6F20776F6C6653534C2100"); + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 30), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + + /* Dump Der */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_DUMP_DER; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 35); + BIO_read(bio, (void*)rbuf, 35); + AssertStrEQ((char*)rbuf, "#040F48656C6C6F20776F6C6653534C2100"); + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 2), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 30), 1); + AssertIntEQ(wolfSSL_ASN1_STRING_print_ex(fixed, asn_str, flags), 0); + + /* Dump All + Show type */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_SHOW_TYPE; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); + AssertIntEQ(p_len, 44); + BIO_read(bio, (void*)rbuf, 44); + AssertStrEQ((char*)rbuf, "OCTET STRING:#48656C6C6F20776F6C6653534C2100"); + + /* Dump All + Show type - Negative Integer. */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_SHOW_TYPE; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, neg_int, flags); + AssertIntEQ(p_len, 11); + BIO_read(bio, (void*)rbuf, 11); + AssertStrEQ((char*)rbuf, "INTEGER:#FF"); + + /* Dump All + Show type - Negative Enumerated. */ + XMEMSET(rbuf, 0, 255); + flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_SHOW_TYPE; + p_len = wolfSSL_ASN1_STRING_print_ex(bio, neg_enum, flags); + AssertIntEQ(p_len, 14); + BIO_read(bio, (void*)rbuf, 14); + AssertStrEQ((char*)rbuf, "ENUMERATED:#FF"); + + BIO_free(fixed); + BIO_free(bio); + ASN1_STRING_free(asn_str); + ASN1_STRING_free(esc_str); + ASN1_STRING_free(neg_int); + ASN1_STRING_free(neg_enum); + + AssertStrEQ(wolfSSL_ASN1_tag2str(-1), "(unknown)"); + AssertStrEQ(wolfSSL_ASN1_tag2str(31), "(unknown)"); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_UNIVERSALSTRING_to_string(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_ALL) && !defined(NO_ASN) + ASN1_STRING* asn1str_test; + ASN1_STRING* asn1str_answer; + /* Each character is encoded using 4 bytes */ + char input[] = { + 0, 0, 0, 'T', + 0, 0, 0, 'e', + 0, 0, 0, 's', + 0, 0, 0, 't', + }; + char output[] = "Test"; + char badInput[] = { + 1, 0, 0, 'T', + 0, 1, 0, 'e', + 0, 0, 1, 's', + }; + + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(NULL), 0); + /* Test wrong type. */ + AssertNotNull(asn1str_test = ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 0); + ASN1_STRING_free(asn1str_test); + + AssertNotNull(asn1str_test = ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)); + + /* Test bad length. */ + AssertIntEQ(ASN1_STRING_set(asn1str_test, input, sizeof(input) - 1), 1); + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 0); + /* Test bad input. */ + AssertIntEQ(ASN1_STRING_set(asn1str_test, badInput + 0, 4), 1); + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 0); + AssertIntEQ(ASN1_STRING_set(asn1str_test, badInput + 4, 4), 1); + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 0); + AssertIntEQ(ASN1_STRING_set(asn1str_test, badInput + 8, 4), 1); + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 0); + + AssertIntEQ(ASN1_STRING_set(asn1str_test, input, sizeof(input)), 1); + AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 1); + + AssertNotNull( + asn1str_answer = ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)); + AssertIntEQ(ASN1_STRING_set(asn1str_answer, output, sizeof(output)-1), 1); + + AssertIntEQ(ASN1_STRING_cmp(asn1str_test, asn1str_answer), 0); + + ASN1_STRING_free(asn1str_test); + ASN1_STRING_free(asn1str_answer); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_ALL && !NO_ASN */ + return res; +} + +static int test_wolfSSL_ASN1_GENERALIZEDTIME_free(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) + WOLFSSL_ASN1_GENERALIZEDTIME* asn1_gtime; + unsigned char nullstr[32]; + + XMEMSET(nullstr, 0, 32); + asn1_gtime = (WOLFSSL_ASN1_GENERALIZEDTIME*)XMALLOC( + sizeof(WOLFSSL_ASN1_GENERALIZEDTIME), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (asn1_gtime) { + XMEMCPY(asn1_gtime->data,"20180504123500Z",ASN_GENERALIZED_TIME_SIZE); + + wolfSSL_ASN1_GENERALIZEDTIME_free(asn1_gtime); + AssertIntEQ(0, XMEMCMP(asn1_gtime->data, nullstr, 32)); + + XFREE(asn1_gtime, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wolfSSL_ASN1_GENERALIZEDTIME_free(NULL); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA */ + return res; +} + +static int test_wolfSSL_ASN1_GENERALIZEDTIME_print(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) + WOLFSSL_ASN1_GENERALIZEDTIME gtime; + BIO* bio; + unsigned char buf[24]; + int i; + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + BIO_set_write_buf_size(bio, 24); + + XMEMSET(>ime, 0, sizeof(WOLFSSL_ASN1_GENERALIZEDTIME)); + XMEMCPY(gtime.data, "20180504123500Z", ASN_GENERALIZED_TIME_SIZE); + gtime.length = ASN_GENERALIZED_TIME_SIZE; + /* Type not set. */ + AssertIntEQ(wolfSSL_ASN1_GENERALIZEDTIME_print(bio, >ime), 0); + gtime.type = V_ASN1_GENERALIZEDTIME; + + /* Invalid parameters testing. */ + AssertIntEQ(wolfSSL_ASN1_GENERALIZEDTIME_print(NULL, NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_ASN1_GENERALIZEDTIME_print(bio, NULL), BAD_FUNC_ARG); + AssertIntEQ(wolfSSL_ASN1_GENERALIZEDTIME_print(NULL, >ime), BAD_FUNC_ARG); + + AssertIntEQ(wolfSSL_ASN1_GENERALIZEDTIME_print(bio, >ime), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 20); + AssertIntEQ(XMEMCMP(buf, "May 04 12:35:00 2018", 20), 0); + + BIO_free(bio); + + AssertNotNull(bio = BIO_new(wolfSSL_BIO_s_fixed_mem())); + for (i = 0; i < 20; i++) { + AssertIntEQ(BIO_set_write_buf_size(bio, i), 1); + AssertIntEQ(wolfSSL_ASN1_GENERALIZEDTIME_print(bio, >ime), 0); + } + BIO_free(bio); + + wolfSSL_ASN1_GENERALIZEDTIME_free(>ime); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA */ + return res; +} + +static int test_wolfSSL_ASN1_TIME(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) + WOLFSSL_ASN1_TIME* asn_time; + unsigned char *data; + + AssertNotNull(asn_time = ASN1_TIME_new()); + +#ifndef NO_WOLFSSL_STUB + AssertNotNull(ASN1_TIME_set(asn_time, 1)); +#endif + AssertIntEQ(ASN1_TIME_set_string(NULL, NULL), 0); + AssertIntEQ(ASN1_TIME_set_string(asn_time, NULL), 0); + AssertIntEQ(ASN1_TIME_set_string(NULL, + "String longer than CTC_DATA_SIZE that is 32 bytes"), 0); + AssertIntEQ(ASN1_TIME_set_string(NULL, "101219181011Z"), 1); + AssertIntEQ(ASN1_TIME_set_string(asn_time, "101219181011Z"), 1); + + AssertIntEQ(wolfSSL_ASN1_TIME_get_length(NULL), 0); + AssertIntEQ(wolfSSL_ASN1_TIME_get_length(asn_time), ASN_UTC_TIME_SIZE - 1); + AssertNull(wolfSSL_ASN1_TIME_get_data(NULL)); + AssertNotNull(data = wolfSSL_ASN1_TIME_get_data(asn_time)); + AssertIntEQ(XMEMCMP(data, "101219181011Z", 14), 0); + + AssertIntEQ(ASN1_TIME_check(NULL), 0); + AssertIntEQ(ASN1_TIME_check(asn_time), 1); + + ASN1_TIME_free(asn_time); + ASN1_TIME_free(NULL); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_TIME_to_string(void) +{ + int res = TEST_SKIPPED; +#ifndef NO_ASN_TIME +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + WOLFSSL_ASN1_TIME* t; + char buf[ASN_GENERALIZED_TIME_SIZE]; + + AssertNotNull((t = ASN1_TIME_new())); + AssertIntEQ(ASN1_TIME_set_string(t, "030222211515Z"), 1); + + /* Invalid parameter testing. */ + AssertNull(ASN1_TIME_to_string(NULL, NULL, 4)); + AssertNull(ASN1_TIME_to_string(t, NULL, 4)); + AssertNull(ASN1_TIME_to_string(NULL, buf, 4)); + AssertNull(ASN1_TIME_to_string(NULL, NULL, 5)); + AssertNull(ASN1_TIME_to_string(NULL, buf, 5)); + AssertNull(ASN1_TIME_to_string(t, NULL, 5)); + AssertNull(ASN1_TIME_to_string(t, buf, 4)); + /* Buffer needs to be longer than minimum of 5 characters. */ + AssertNull(ASN1_TIME_to_string(t, buf, 5)); + + ASN1_TIME_free(t); + + res = TEST_RES_CHECK(1); +#endif +#endif /* NO_ASN_TIME */ + return res; +} + +static int test_wolfSSL_ASN1_TIME_diff_compare(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) + ASN1_TIME* fromTime; + ASN1_TIME* closeToTime; + ASN1_TIME* toTime; + ASN1_TIME* invalidTime; + int daysDiff; + int secsDiff; + + AssertNotNull((fromTime = ASN1_TIME_new())); + /* Feb 22, 2003, 21:15:15 */ + AssertIntEQ(ASN1_TIME_set_string(fromTime, "030222211515Z"), 1); + AssertNotNull((closeToTime = ASN1_TIME_new())); + /* Feb 22, 2003, 21:16:15 */ + AssertIntEQ(ASN1_TIME_set_string(closeToTime, "030222211615Z"), 1); + AssertNotNull((toTime = ASN1_TIME_new())); + /* Dec 19, 2010, 18:10:11 */ + AssertIntEQ(ASN1_TIME_set_string(toTime, "101219181011Z"), 1); + AssertNotNull((invalidTime = ASN1_TIME_new())); + /* Dec 19, 2010, 18:10:11 but 'U' instead of 'Z' which is invalid. */ + AssertIntEQ(ASN1_TIME_set_string(invalidTime, "102519181011U"), 1); + + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, invalidTime), 0); + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, invalidTime, toTime), 0); + + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), 1); + + /* Error conditions. */ + AssertIntEQ(ASN1_TIME_diff(NULL, &secsDiff, fromTime, toTime), 0); + AssertIntEQ(ASN1_TIME_diff(&daysDiff, NULL, fromTime, toTime), 0); + + /* If both times are NULL, difference is 0. */ + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, NULL, NULL), 1); + AssertIntEQ(daysDiff, 0); + AssertIntEQ(secsDiff, 0); + + /* If one time is NULL, it defaults to the current time. */ + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, NULL, toTime), 1); + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, NULL), 1); + + /* Normal operation. Both times non-NULL. */ + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), 1); + AssertIntEQ(daysDiff, 2856); + AssertIntEQ(secsDiff, 75296); + /* Swapping the times should return negative values. */ + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, toTime, fromTime), 1); + AssertIntEQ(daysDiff, -2856); + AssertIntEQ(secsDiff, -75296); + + /* Compare with invalid time string. */ + AssertIntEQ(ASN1_TIME_compare(fromTime, invalidTime), -2); + AssertIntEQ(ASN1_TIME_compare(invalidTime, toTime), -2); + /* Compare with days difference of 0. */ + AssertIntEQ(ASN1_TIME_compare(fromTime, closeToTime), -1); + AssertIntEQ(ASN1_TIME_compare(closeToTime, fromTime), 1); + /* Days and seconds differences not 0. */ + AssertIntEQ(ASN1_TIME_compare(fromTime, toTime), -1); + AssertIntEQ(ASN1_TIME_compare(toTime, fromTime), 1); + /* Same time. */ + AssertIntEQ(ASN1_TIME_compare(fromTime, fromTime), 0); + + /* Compare regression test: No seconds difference, just difference in days. + */ + ASN1_TIME_set_string(fromTime, "19700101000000Z"); + ASN1_TIME_set_string(toTime, "19800101000000Z"); + AssertIntEQ(ASN1_TIME_compare(fromTime, toTime), -1); + AssertIntEQ(ASN1_TIME_compare(toTime, fromTime), 1); + AssertIntEQ(ASN1_TIME_compare(fromTime, fromTime), 0); + + /* Edge case with Unix epoch. */ + AssertNotNull(ASN1_TIME_set_string(fromTime, "19700101000000Z")); + AssertNotNull(ASN1_TIME_set_string(toTime, "19800101000000Z")); + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), 1); + AssertIntEQ(daysDiff, 3652); + AssertIntEQ(secsDiff, 0); + + /* Edge case with year > 2038 (year 2038 problem). */ + AssertNotNull(ASN1_TIME_set_string(toTime, "99991231235959Z")); + AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), 1); + AssertIntEQ(daysDiff, 2932896); + AssertIntEQ(secsDiff, 86399); + + ASN1_TIME_free(fromTime); + ASN1_TIME_free(closeToTime); + ASN1_TIME_free(toTime); + ASN1_TIME_free(invalidTime); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_TIME_adj(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) \ +&& !defined(USER_TIME) && !defined(TIME_OVERRIDES) + const int year = 365*24*60*60; + const int day = 24*60*60; + const int hour = 60*60; + const int mini = 60; + const byte asn_utc_time = ASN_UTC_TIME; +#if !defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT) + const byte asn_gen_time = ASN_GENERALIZED_TIME; +#endif + WOLFSSL_ASN1_TIME* asn_time; + WOLFSSL_ASN1_TIME* s; + int offset_day; + long offset_sec; + char date_str[CTC_DATE_SIZE + 1]; + time_t t; + + AssertNotNull(s = wolfSSL_ASN1_TIME_new()); + /* UTC notation test */ + /* 2000/2/15 20:30:00 */ + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 7 * day; + offset_day = 7; + offset_sec = 45 * mini; + /* offset_sec = -45 * min;*/ + AssertNotNull(asn_time = + wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec)); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "000222211500Z", 13)); + + /* negative offset */ + offset_sec = -45 * mini; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertNotNull(asn_time); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "000222194500Z", 13)); + + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); + XMEMSET(date_str, 0, sizeof(date_str)); + + /* Generalized time will overflow time_t if not long */ +#if !defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT) + s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, + DYNAMIC_TYPE_OPENSSL); + /* GeneralizedTime notation test */ + /* 2055/03/01 09:00:00 */ + t = (time_t)85 * year + 59 * day + 9 * hour + 21 * day; + offset_day = 12; + offset_sec = 10 * mini; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_gen_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "20550313091000Z", 15)); + + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); + XMEMSET(date_str, 0, sizeof(date_str)); +#endif /* !TIME_T_NOT_64BIT && !NO_64BIT */ + + /* if WOLFSSL_ASN1_TIME struct is not allocated */ + s = NULL; + + t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 15 + 7 * day; + offset_day = 7; + offset_sec = 45 * mini; + asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + + asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, offset_sec); + AssertTrue(asn_time->type == asn_utc_time); + XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); + date_str[CTC_DATE_SIZE] = '\0'; + AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); + XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_TIME_to_tm(void) +{ + int res = TEST_SKIPPED; +#if (defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) \ + && !defined(NO_ASN_TIME) + ASN1_TIME asnTime; + struct tm tm; + + XMEMSET(&asnTime, 0, sizeof(ASN1_TIME)); + AssertIntEQ(ASN1_TIME_set_string(&asnTime, "000222211515Z"), 1); + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, NULL), 1); + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 1); + + AssertIntEQ(tm.tm_sec, 15); + AssertIntEQ(tm.tm_min, 15); + AssertIntEQ(tm.tm_hour, 21); + AssertIntEQ(tm.tm_mday, 22); + AssertIntEQ(tm.tm_mon, 1); + AssertIntEQ(tm.tm_year, 100); + AssertIntEQ(tm.tm_isdst, 0); +#ifdef XMKTIME + AssertIntEQ(tm.tm_wday, 2); + AssertIntEQ(tm.tm_yday, 52); +#endif + + AssertIntEQ(ASN1_TIME_set_string(&asnTime, "500222211515Z"), 1); + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 1); + AssertIntEQ(tm.tm_year, 50); + + /* Get current time. */ + AssertIntEQ(ASN1_TIME_to_tm(NULL, NULL), 0); + AssertIntEQ(ASN1_TIME_to_tm(NULL, &tm), 1); + + XMEMSET(&asnTime, 0, sizeof(ASN1_TIME)); + /* 0 length. */ + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 0); + /* No type. */ + asnTime.length = 1; + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 0); + /* Not UTCTIME length. */ + asnTime.type = V_ASN1_UTCTIME; + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 0); + /* Not GENERALIZEDTIME length. */ + asnTime.type = V_ASN1_GENERALIZEDTIME; + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 0); + + /* Not Zulu timezone. */ + AssertIntEQ(ASN1_TIME_set_string(&asnTime, "000222211515U"), 1); + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 0); + AssertIntEQ(ASN1_TIME_set_string(&asnTime, "20000222211515U"), 1); + AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 0); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_TIME_to_generalizedtime(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) + WOLFSSL_ASN1_TIME *t; + WOLFSSL_ASN1_TIME *out; + WOLFSSL_ASN1_TIME *gtime; + int tlen = 0; + unsigned char *data; + + AssertNotNull(t = wolfSSL_ASN1_TIME_new()); + AssertNull(wolfSSL_ASN1_TIME_to_generalizedtime(NULL, &out)); + /* type not set. */ + AssertNull(wolfSSL_ASN1_TIME_to_generalizedtime(t, &out)); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* UTC Time test */ + AssertNotNull(t = wolfSSL_ASN1_TIME_new()); + XMEMSET(t->data, 0, ASN_GENERALIZED_TIME_SIZE); + t->type = ASN_UTC_TIME; + t->length = ASN_UTC_TIME_SIZE; + XMEMCPY(t->data, "050727123456Z", ASN_UTC_TIME_SIZE); + + tlen = wolfSSL_ASN1_TIME_get_length(t); + AssertIntEQ(tlen, ASN_UTC_TIME_SIZE); + data = wolfSSL_ASN1_TIME_get_data(t); + AssertStrEQ((char*)data, "050727123456Z"); + + out = NULL; + gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); + wolfSSL_ASN1_TIME_free(gtime); + AssertNotNull(out = wolfSSL_ASN1_TIME_new()); + gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); + AssertPtrEq(gtime, out); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "20050727123456Z"); + + /* Generalized Time test */ + XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); + XMEMSET(out, 0, ASN_GENERALIZED_TIME_SIZE); + XMEMSET(data, 0, ASN_GENERALIZED_TIME_SIZE); + t->type = ASN_GENERALIZED_TIME; + t->length = ASN_GENERALIZED_TIME_SIZE; + XMEMCPY(t->data, "20050727123456Z", ASN_GENERALIZED_TIME_SIZE); + + tlen = wolfSSL_ASN1_TIME_get_length(t); + AssertIntEQ(tlen, ASN_GENERALIZED_TIME_SIZE); + data = wolfSSL_ASN1_TIME_get_data(t); + AssertStrEQ((char*)data, "20050727123456Z"); + gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "20050727123456Z"); + + /* UTC Time to Generalized Time 1900's test */ + XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); + XMEMSET(out, 0, ASN_GENERALIZED_TIME_SIZE); + XMEMSET(data, 0, ASN_GENERALIZED_TIME_SIZE); + t->type = ASN_UTC_TIME; + t->length = ASN_UTC_TIME_SIZE; + XMEMCPY(t->data, "500727123456Z", ASN_UTC_TIME_SIZE); + + gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "19500727123456Z"); + XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* Null parameter test */ + XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); + gtime = NULL; + out = NULL; + t->type = ASN_UTC_TIME; + t->length = ASN_UTC_TIME_SIZE; + XMEMCPY(t->data, "050727123456Z", ASN_UTC_TIME_SIZE); + AssertNotNull(gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, NULL)); + AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); + AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); + AssertStrEQ((char*)gtime->data, "20050727123456Z"); + + XFREE(gtime, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_TIME_print(void) +{ + int res = TEST_SKIPPED; +#if !defined(NO_CERTS) && !defined(NO_RSA) && !defined(NO_BIO) && \ + (defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_ALL)) && defined(USE_CERT_BUFFERS_2048) && \ + !defined(NO_ASN_TIME) + BIO* bio; + BIO* fixed; + X509* x509; + const unsigned char* der = client_cert_der_2048; + ASN1_TIME* notAfter; + ASN1_TIME* notBefore; + unsigned char buf[25]; + + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertNotNull(fixed = BIO_new(wolfSSL_BIO_s_fixed_mem())); + AssertNotNull(x509 = wolfSSL_X509_load_certificate_buffer(der, + sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); + AssertNotNull(notBefore = X509_get_notBefore(x509)); + + AssertIntEQ(ASN1_TIME_print(NULL, NULL), 0); + AssertIntEQ(ASN1_TIME_print(bio, NULL), 0); + AssertIntEQ(ASN1_TIME_print(NULL, notBefore), 0); + + AssertIntEQ(ASN1_TIME_print(bio, notBefore), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); + AssertIntEQ(XMEMCMP(buf, "Dec 16 21:17:49 2022 GMT", sizeof(buf) - 1), 0); + + /* Test BIO_write fails. */ + AssertIntEQ(BIO_set_write_buf_size(fixed, 0), 1); + AssertIntEQ(ASN1_TIME_print(fixed, notBefore), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 1), 1); + AssertIntEQ(ASN1_TIME_print(fixed, notBefore), 0); + AssertIntEQ(BIO_set_write_buf_size(fixed, 23), 1); + AssertIntEQ(ASN1_TIME_print(fixed, notBefore), 0); + + /* create a bad time and test results */ + AssertNotNull(notAfter = X509_get_notAfter(x509)); + AssertIntEQ(ASN1_TIME_check(notAfter), 1); + notAfter->data[8] = 0; + notAfter->data[3] = 0; + AssertIntNE(ASN1_TIME_print(bio, notAfter), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); + AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); + AssertIntEQ(ASN1_TIME_check(notAfter), 0); + + BIO_free(bio); + BIO_free(fixed); + X509_free(x509); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_ASN1_UTCTIME_print(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) && !defined(NO_BIO) + BIO* bio; + ASN1_UTCTIME* utc = NULL; + unsigned char buf[25]; + const char* validDate = "190424111501Z"; /* UTC = YYMMDDHHMMSSZ */ + const char* invalidDate = "190424111501X"; /* UTC = YYMMDDHHMMSSZ */ + const char* genDate = "20190424111501Z"; /* GEN = YYYYMMDDHHMMSSZ */ + + /* Valid date */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + AssertNotNull(utc = (ASN1_UTCTIME*)XMALLOC(sizeof(ASN1_UTCTIME), NULL, + DYNAMIC_TYPE_ASN1)); + utc->type = ASN_UTC_TIME; + utc->length = ASN_UTC_TIME_SIZE; + XMEMCPY(utc->data, (byte*)validDate, ASN_UTC_TIME_SIZE); + + AssertIntEQ(ASN1_UTCTIME_print(NULL, NULL), 0); + AssertIntEQ(ASN1_UTCTIME_print(bio, NULL), 0); + AssertIntEQ(ASN1_UTCTIME_print(NULL, utc), 0); + + AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 1); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); + AssertIntEQ(XMEMCMP(buf, "Apr 24 11:15:01 2019 GMT", sizeof(buf)-1), 0); + + XMEMSET(buf, 0, sizeof(buf)); + BIO_free(bio); + + /* Invalid format */ + AssertNotNull(bio = BIO_new(BIO_s_mem())); + utc->type = ASN_UTC_TIME; + utc->length = ASN_UTC_TIME_SIZE; + XMEMCPY(utc->data, (byte*)invalidDate, ASN_UTC_TIME_SIZE); + AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 0); + AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); + AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); + + /* Invalid type */ + utc->type = ASN_GENERALIZED_TIME; + utc->length = ASN_GENERALIZED_TIME_SIZE; + XMEMCPY(utc->data, (byte*)genDate, ASN_GENERALIZED_TIME_SIZE); + AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 0); + + XFREE(utc, NULL, DYNAMIC_TYPE_ASN1); + BIO_free(bio); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && !NO_ASN_TIME && !NO_BIO */ + return res; +} + +static int test_wolfSSL_ASN1_TYPE(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_WPAS) + WOLFSSL_ASN1_TYPE* t; + WOLFSSL_ASN1_OBJECT* obj; +#ifndef NO_ASN_TIME + WOLFSSL_ASN1_TIME* time; +#endif + WOLFSSL_ASN1_STRING* str; + unsigned char data[] = { 0x00 }; + + ASN1_TYPE_set(NULL, V_ASN1_NULL, NULL); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + ASN1_TYPE_set(t, V_ASN1_EOC, NULL); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + ASN1_TYPE_set(t, V_ASN1_NULL, NULL); + ASN1_TYPE_set(t, V_ASN1_NULL, data); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(obj = wolfSSL_ASN1_OBJECT_new()); + ASN1_TYPE_set(t, V_ASN1_OBJECT, obj); + wolfSSL_ASN1_TYPE_free(t); + +#ifndef NO_ASN_TIME + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(time = wolfSSL_ASN1_TIME_new()); + ASN1_TYPE_set(t, V_ASN1_UTCTIME, time); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(time = wolfSSL_ASN1_TIME_new()); + ASN1_TYPE_set(t, V_ASN1_GENERALIZEDTIME, time); + wolfSSL_ASN1_TYPE_free(t); +#endif + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(str = wolfSSL_ASN1_STRING_new()); + ASN1_TYPE_set(t, V_ASN1_UTF8STRING, str); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(str = wolfSSL_ASN1_STRING_new()); + ASN1_TYPE_set(t, V_ASN1_PRINTABLESTRING, str); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(str = wolfSSL_ASN1_STRING_new()); + ASN1_TYPE_set(t, V_ASN1_T61STRING, str); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(str = wolfSSL_ASN1_STRING_new()); + ASN1_TYPE_set(t, V_ASN1_IA5STRING, str); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(str = wolfSSL_ASN1_STRING_new()); + ASN1_TYPE_set(t, V_ASN1_UNIVERSALSTRING, str); + wolfSSL_ASN1_TYPE_free(t); + + AssertNotNull(t = wolfSSL_ASN1_TYPE_new()); + AssertNotNull(str = wolfSSL_ASN1_STRING_new()); + ASN1_TYPE_set(t, V_ASN1_SEQUENCE, str); + wolfSSL_ASN1_TYPE_free(t); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +/* Testing code used in dpp.c in hostap */ +#if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) +typedef struct { + /* AlgorithmIdentifier ecPublicKey with optional parameters present + * as an OID identifying the curve */ + X509_ALGOR *alg; + /* Compressed format public key per ANSI X9.63 */ + ASN1_BIT_STRING *pub_key; +} DPP_BOOTSTRAPPING_KEY; + +ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY) + +IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY) + +typedef struct { + ASN1_INTEGER *integer; +} TEST_ASN1; + +#define WOLFSSL_ASN1_INTEGER_ASN1 2 +ASN1_SEQUENCE(TEST_ASN1) = { + ASN1_SIMPLE(TEST_ASN1, integer, ASN1_INTEGER), +} ASN1_SEQUENCE_END(TEST_ASN1) + +IMPLEMENT_ASN1_FUNCTIONS(TEST_ASN1) +#endif + +static int test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS(void) +{ + int res = TEST_SKIPPED; + /* Testing code used in dpp.c in hostap */ +#if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) + EC_KEY *eckey; + EVP_PKEY *key; + size_t len; + unsigned char *der = NULL; + DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; + const unsigned char *in = ecc_clikey_der_256; + const EC_GROUP *group; + const EC_POINT *point; + int nid; + TEST_ASN1 test_asn1; + const unsigned char badObjDer[] = { 0x06, 0x00 }; + const unsigned char goodObjDer[] = { + 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01 + }; + WOLFSSL_ASN1_ITEM emptyTemplate; + + XMEMSET(&emptyTemplate, 0, sizeof(WOLFSSL_ASN1_ITEM)); + + AssertNotNull(bootstrap = DPP_BOOTSTRAPPING_KEY_new()); + + der = NULL; + AssertIntEQ(i2d_DPP_BOOTSTRAPPING_KEY(NULL, &der), 0); + AssertIntEQ(wolfSSL_ASN1_item_i2d(bootstrap, &der, NULL), 0); + AssertIntEQ(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 0); + + AssertNotNull(key = d2i_PrivateKey(EVP_PKEY_EC, NULL, &in, + (long)sizeof_ecc_clikey_der_256)); + AssertNotNull(eckey = EVP_PKEY_get1_EC_KEY(key)); + AssertNotNull(group = EC_KEY_get0_group(eckey)); + AssertNotNull(point = EC_KEY_get0_public_key(eckey)); + nid = EC_GROUP_get_curve_name(group); + + AssertIntEQ(X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), + V_ASN1_OBJECT, OBJ_nid2obj(nid)), 1); + AssertIntEQ(EC_POINT_point2oct(group, point, 0, NULL, 0, NULL), 0); +#ifdef HAVE_COMP_KEY + AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + NULL, 0, NULL)), 0); +#else + AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, NULL)), 0); +#endif + AssertNotNull(der = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1)); +#ifdef HAVE_COMP_KEY + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len-1, NULL), 0); + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len, NULL), len); +#else + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + der, len-1, NULL), 0); + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + der, len, NULL), len); +#endif + bootstrap->pub_key->data = der; + bootstrap->pub_key->length = (int)len; + /* Not actually used */ + bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + AssertIntGT(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, NULL), 0); + der = NULL; + AssertIntGT(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 0); + AssertIntGT(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 0); + + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); + EVP_PKEY_free(key); + EC_KEY_free(eckey); + DPP_BOOTSTRAPPING_KEY_free(bootstrap); + DPP_BOOTSTRAPPING_KEY_free(NULL); + + /* Create bootstrap key with bad OBJECT_ID DER data, parameter that is + * a NULL and an empty BIT_STRING. */ + AssertNotNull(bootstrap = DPP_BOOTSTRAPPING_KEY_new()); + bootstrap->alg->algorithm = wolfSSL_ASN1_OBJECT_new(); + bootstrap->alg->algorithm->obj = badObjDer; + bootstrap->alg->algorithm->objSz = (unsigned int)sizeof(badObjDer); + bootstrap->alg->parameter = wolfSSL_ASN1_TYPE_new(); + bootstrap->alg->parameter->type = V_ASN1_NULL; + bootstrap->alg->parameter->value.ptr = NULL; + bootstrap->pub_key->data = NULL; + bootstrap->pub_key->length = 0; + /* Not actually used */ + bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + /* Encode with bad OBJECT_ID. */ + der = NULL; + AssertIntEQ(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 0); + + /* Fix OBJECT_ID and encode with empty BIT_STRING. */ + bootstrap->alg->algorithm->obj = goodObjDer; + bootstrap->alg->algorithm->objSz = (unsigned int)sizeof(goodObjDer); + bootstrap->alg->algorithm->grp = 2; + der = NULL; + AssertIntEQ(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 16); + AssertIntEQ(wolfSSL_ASN1_item_i2d(bootstrap, &der, &emptyTemplate), 0); + XFREE(der, NULL, DYNAMIC_TYPE_ASN1); + DPP_BOOTSTRAPPING_KEY_free(bootstrap); + + /* Test error cases. */ + AssertNull(TEST_ASN1_new()); + AssertNull(wolfSSL_ASN1_item_new(NULL)); + TEST_ASN1_free(NULL); + XMEMSET(&test_asn1, 0, sizeof(TEST_ASN1)); + AssertIntEQ(i2d_TEST_ASN1(&test_asn1, &der), 0); + + res = TEST_RES_CHECK(1); +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* OPENSSL_ALL && HAVE_ECC && USE_CERT_BUFFERS_256 */ + return res; +} + + static int test_wolfSSL_lhash(void) { int res = TEST_SKIPPED; @@ -32063,196 +34406,6 @@ static int test_wolfSSL_X509_check_private_key(void) } -static int test_wolfSSL_ASN1_TIME_print(void) -{ - int res = TEST_SKIPPED; - #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_RSA) \ - && (defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY)) && defined(USE_CERT_BUFFERS_2048) && \ - !defined(NO_BIO) - BIO* bio; - X509* x509; - const unsigned char* der = client_cert_der_2048; - ASN1_TIME* t; - unsigned char buf[25]; - - AssertNotNull(bio = BIO_new(BIO_s_mem())); - AssertNotNull(x509 = wolfSSL_X509_load_certificate_buffer(der, - sizeof_client_cert_der_2048, WOLFSSL_FILETYPE_ASN1)); - AssertIntEQ(ASN1_TIME_print(bio, X509_get_notBefore(x509)), 1); - AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); - AssertIntEQ(XMEMCMP(buf, "Dec 16 21:17:49 2022 GMT", sizeof(buf) - 1), 0); - - /* create a bad time and test results */ - AssertNotNull(t = X509_get_notAfter(x509)); - AssertIntEQ(ASN1_TIME_check(t), WOLFSSL_SUCCESS); - t->data[8] = 0; - t->data[3] = 0; - AssertIntNE(ASN1_TIME_print(bio, t), 1); - AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); - AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); - AssertIntEQ(ASN1_TIME_check(t), WOLFSSL_FAILURE); - - BIO_free(bio); - X509_free(x509); - - res = TEST_RES_CHECK(1); - #endif - return res; -} - -static int test_wolfSSL_ASN1_UTCTIME_print(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) && !defined(NO_BIO) - BIO* bio; - ASN1_UTCTIME* utc = NULL; - unsigned char buf[25]; - const char* validDate = "190424111501Z"; /* UTC = YYMMDDHHMMSSZ */ - const char* invalidDate = "190424111501X"; /* UTC = YYMMDDHHMMSSZ */ - - /* NULL parameter check */ - AssertNotNull(bio = BIO_new(BIO_s_mem())); - AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 0); - BIO_free(bio); - - /* Valid date */ - AssertNotNull(bio = BIO_new(BIO_s_mem())); - AssertNotNull(utc = (ASN1_UTCTIME*)XMALLOC(sizeof(ASN1_UTCTIME), NULL, - DYNAMIC_TYPE_ASN1)); - utc->type = ASN_UTC_TIME; - utc->length = ASN_UTC_TIME_SIZE; - XMEMCPY(utc->data, (byte*)validDate, ASN_UTC_TIME_SIZE); - AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 1); - AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 24); - AssertIntEQ(XMEMCMP(buf, "Apr 24 11:15:01 2019 GMT", sizeof(buf)-1), 0); - - XMEMSET(buf, 0, sizeof(buf)); - BIO_free(bio); - - /* Invalid format */ - AssertNotNull(bio = BIO_new(BIO_s_mem())); - utc->type = ASN_UTC_TIME; - utc->length = ASN_UTC_TIME_SIZE; - XMEMCPY(utc->data, (byte*)invalidDate, ASN_UTC_TIME_SIZE); - AssertIntEQ(ASN1_UTCTIME_print(bio, utc), 0); - AssertIntEQ(BIO_read(bio, buf, sizeof(buf)), 14); - AssertIntEQ(XMEMCMP(buf, "Bad time value", 14), 0); - - XFREE(utc, NULL, DYNAMIC_TYPE_ASN1); - BIO_free(bio); - - res = TEST_RES_CHECK(1); -#endif /* OPENSSL_EXTRA && !NO_ASN_TIME && !NO_BIO */ - return res; -} - -static int test_wolfSSL_ASN1_TIME_diff_compare(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) - ASN1_TIME* fromTime; - ASN1_TIME* toTime; - int daysDiff; - int secsDiff; - - AssertNotNull((fromTime = ASN1_TIME_new())); - /* Feb 22, 2003, 21:15:15 */ - AssertIntEQ(ASN1_TIME_set_string(fromTime, "030222211515Z"), WOLFSSL_SUCCESS); - AssertNotNull((toTime = ASN1_TIME_new())); - /* Dec 19, 2010, 18:10:11 */ - AssertIntEQ(ASN1_TIME_set_string(toTime, "101219181011Z"), WOLFSSL_SUCCESS); - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), WOLFSSL_SUCCESS); - - /* Error conditions. */ - AssertIntEQ(ASN1_TIME_diff(NULL, &secsDiff, fromTime, toTime), - WOLFSSL_FAILURE); - AssertIntEQ(ASN1_TIME_diff(&daysDiff, NULL, fromTime, toTime), - WOLFSSL_FAILURE); - - /* If both times are NULL, difference is 0. */ - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, NULL, NULL), - WOLFSSL_SUCCESS); - AssertIntEQ(daysDiff, 0); - AssertIntEQ(secsDiff, 0); - - /* If one time is NULL, it defaults to the current time. */ - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, NULL, toTime), - WOLFSSL_SUCCESS); - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, NULL), - WOLFSSL_SUCCESS); - - /* Normal operation. Both times non-NULL. */ - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), - WOLFSSL_SUCCESS); - AssertIntEQ(daysDiff, 2856); - AssertIntEQ(secsDiff, 75296); - /* Swapping the times should return negative values. */ - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, toTime, fromTime), - WOLFSSL_SUCCESS); - AssertIntEQ(daysDiff, -2856); - AssertIntEQ(secsDiff, -75296); - - AssertIntEQ(ASN1_TIME_compare(fromTime, toTime), -1); - AssertIntEQ(ASN1_TIME_compare(toTime, fromTime), 1); - AssertIntEQ(ASN1_TIME_compare(fromTime, fromTime), 0); - - /* Compare regression test: No seconds difference, just difference in days. - */ - ASN1_TIME_set_string(fromTime, "19700101000000Z"); - ASN1_TIME_set_string(toTime, "19800101000000Z"); - AssertIntEQ(ASN1_TIME_compare(fromTime, toTime), -1); - AssertIntEQ(ASN1_TIME_compare(toTime, fromTime), 1); - AssertIntEQ(ASN1_TIME_compare(fromTime, fromTime), 0); - - /* Edge case with Unix epoch. */ - AssertNotNull(ASN1_TIME_set_string(fromTime, "19700101000000Z")); - AssertNotNull(ASN1_TIME_set_string(toTime, "19800101000000Z")); - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), - WOLFSSL_SUCCESS); - AssertIntEQ(daysDiff, 3652); - AssertIntEQ(secsDiff, 0); - - /* Edge case with year > 2038 (year 2038 problem). */ - AssertNotNull(ASN1_TIME_set_string(toTime, "99991231235959Z")); - AssertIntEQ(ASN1_TIME_diff(&daysDiff, &secsDiff, fromTime, toTime), - WOLFSSL_SUCCESS); - AssertIntEQ(daysDiff, 2932896); - AssertIntEQ(secsDiff, 86399); - - ASN1_TIME_free(fromTime); - ASN1_TIME_free(toTime); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -static int test_wolfSSL_ASN1_GENERALIZEDTIME_free(void) -{ - int res = TEST_SKIPPED; - #if defined(OPENSSL_EXTRA) - WOLFSSL_ASN1_GENERALIZEDTIME* asn1_gtime; - unsigned char nullstr[32]; - - XMEMSET(nullstr, 0, 32); - asn1_gtime = (WOLFSSL_ASN1_GENERALIZEDTIME*)XMALLOC( - sizeof(WOLFSSL_ASN1_GENERALIZEDTIME), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (asn1_gtime) { - XMEMCPY(asn1_gtime->data,"20180504123500Z",ASN_GENERALIZED_TIME_SIZE); - - wolfSSL_ASN1_GENERALIZEDTIME_free(asn1_gtime); - AssertIntEQ(0, XMEMCMP(asn1_gtime->data, nullstr, 32)); - - XFREE(asn1_gtime, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } - - res = TEST_RES_CHECK(1); - #endif /* OPENSSL_EXTRA */ - return res; -} - static int test_wolfSSL_private_keys(void) { @@ -36508,7 +38661,8 @@ static int test_X509_STORE_get0_objects(void) static int test_wolfSSL_BN_CTX(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) WOLFSSL_BN_CTX* bn_ctx; WOLFSSL_BIGNUM* t; @@ -36539,33 +38693,23 @@ static int test_wolfSSL_BN_CTX(void) static int test_wolfSSL_BN(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) BIGNUM* a; BIGNUM* b; BIGNUM* c; BIGNUM* d; - ASN1_INTEGER* ai; BIGNUM emptyBN; /* Setup */ XMEMSET(&emptyBN, 0, sizeof(emptyBN)); /* internal not set emptyBN. */ + AssertNotNull(a = BN_new()); AssertNotNull(b = BN_new()); AssertNotNull(c = BN_dup(b)); AssertNotNull(d = BN_new()); - ai = ASN1_INTEGER_new(); - AssertNotNull(ai); - /* at the moment hard setting since no set function */ - ai->data[0] = 0x02; /* tag for ASN_INTEGER */ - ai->data[1] = 0x01; /* length of integer */ - ai->data[2] = 0x03; - - AssertNotNull(a = ASN1_INTEGER_to_BN(ai, NULL)); - ASN1_INTEGER_free(ai); - - /* Invalid parameter testing. */ BN_free(NULL); AssertNull(BN_dup(NULL)); @@ -36672,7 +38816,8 @@ static int test_wolfSSL_BN(void) static int test_wolfSSL_BN_init(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) #if !defined(USE_INTEGER_HEAP_MATH) && !defined(HAVE_WOLF_BIGINT) BIGNUM* ap; BIGNUM bv; @@ -36901,7 +39046,8 @@ static int test_wolfSSL_BN_word(void) static int test_wolfSSL_BN_bits(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) BIGNUM* a; BIGNUM emptyBN; @@ -36955,7 +39101,8 @@ static int test_wolfSSL_BN_bits(void) static int test_wolfSSL_BN_shift(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) BIGNUM* a; BIGNUM* b; BIGNUM emptyBN; @@ -37005,7 +39152,8 @@ static int test_wolfSSL_BN_shift(void) static int test_wolfSSL_BN_math(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) BIGNUM* a; BIGNUM* b; BIGNUM* r; @@ -37136,7 +39284,8 @@ static int test_wolfSSL_BN_math(void) static int test_wolfSSL_BN_math_mod(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) BIGNUM* a; BIGNUM* b; BIGNUM* m; @@ -37272,7 +39421,8 @@ static int test_wolfSSL_BN_math_mod(void) static int test_wolfSSL_BN_math_other(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) #if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) BIGNUM* a; BIGNUM* b; @@ -37332,7 +39482,7 @@ static int test_wolfSSL_BN_math_other(void) static int test_wolfSSL_BN_rand(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) +#if defined(OPENSSL_EXTRA) && !defined(OPENSSL_EXTRA_NO_BN) BIGNUM* bn; BIGNUM* range; BIGNUM emptyBN; @@ -37480,7 +39630,8 @@ static int test_wolfSSL_BN_rand(void) static int test_wolfSSL_BN_prime(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(WOLFSSL_SP_MATH) +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && \ + !defined(OPENSSL_EXTRA_NO_BN) && !defined(WOLFSSL_SP_MATH) #if defined(WOLFSSL_KEY_GEN) && (!defined(NO_RSA) || !defined(NO_DH) || !defined(NO_DSA)) BIGNUM* a; BIGNUM* add; @@ -38519,93 +40670,6 @@ static int test_wolfSSL_BIO(void) #endif /* !NO_BIO */ -static int test_wolfSSL_ASN1_STRING(void) -{ - int res = TEST_SKIPPED; - #if defined(OPENSSL_EXTRA) - ASN1_STRING* str = NULL; - const char data[] = "hello wolfSSL"; - - AssertNotNull(str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); - AssertIntEQ(ASN1_STRING_type(str), V_ASN1_OCTET_STRING); - AssertIntEQ(ASN1_STRING_set(str, (const void*)data, sizeof(data)), 1); - AssertIntEQ(ASN1_STRING_set(str, (const void*)data, -1), 1); - AssertIntEQ(ASN1_STRING_set(str, NULL, -1), 0); - - ASN1_STRING_free(str); - - res = TEST_RES_CHECK(1); - #endif - return res; -} - -static int test_wolfSSL_ASN1_BIT_STRING(void) -{ - int res = TEST_SKIPPED; -#ifdef OPENSSL_ALL - ASN1_BIT_STRING* str; - - AssertNotNull(str = ASN1_BIT_STRING_new()); - - AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 42, 1), 1); - AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 42), 1); - AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 41), 0); - AssertIntEQ(ASN1_BIT_STRING_set_bit(str, 84, 1), 1); - AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 84), 1); - AssertIntEQ(ASN1_BIT_STRING_get_bit(str, 83), 0); - - ASN1_BIT_STRING_free(str); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -static int test_wolfSSL_a2i_ASN1_INTEGER(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) - BIO *bio, *out; - ASN1_INTEGER* ai; - char buf[] = "123456\n12345\n112345678912345678901234567890\n"; - char tmp[1024]; - int tmpSz; - - const char expected1[] = "123456"; - const char expected2[] = "112345678912345678901234567890"; - - AssertNotNull(bio = BIO_new_mem_buf(buf, -1)); - AssertNotNull(out = BIO_new(BIO_s_mem())); - AssertNotNull(ai = ASN1_INTEGER_new()); - - /* read first line */ - AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS); - AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 6); - XMEMSET(tmp, 0, 1024); - tmpSz = BIO_read(out, tmp, 1024); - AssertIntEQ(tmpSz, 6); - AssertIntEQ(XMEMCMP(tmp, expected1, tmpSz), 0); - - /* fail on second line (not % 2) */ - AssertIntNE(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS); - - /* read 3rd long line */ - AssertIntEQ(a2i_ASN1_INTEGER(bio, ai, tmp, 1024), SSL_SUCCESS); - AssertIntEQ(i2a_ASN1_INTEGER(out, ai), 30); - XMEMSET(tmp, 0, 1024); - tmpSz = BIO_read(out, tmp, 1024); - AssertIntEQ(tmpSz, 30); - AssertIntEQ(XMEMCMP(tmp, expected2, tmpSz), 0); - - BIO_free(out); - BIO_free(bio); - ASN1_INTEGER_free(ai); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - static int test_wolfSSL_a2i_IPADDRESS(void) { int res = TEST_SKIPPED; @@ -38687,125 +40751,6 @@ static int test_wolfSSL_DES_ecb_encrypt(void) return res; } -static int test_wolfSSL_ASN1_TIME_adj(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) \ -&& !defined(USER_TIME) && !defined(TIME_OVERRIDES) - const int year = 365*24*60*60; - const int day = 24*60*60; - const int hour = 60*60; - const int mini = 60; - const byte asn_utc_time = ASN_UTC_TIME; -#if !defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT) - const byte asn_gen_time = ASN_GENERALIZED_TIME; -#endif - WOLFSSL_ASN1_TIME *asn_time, *s; - int offset_day; - long offset_sec; - char date_str[CTC_DATE_SIZE + 1]; - time_t t; - - AssertNotNull(s = wolfSSL_ASN1_TIME_new()); - /* UTC notation test */ - /* 2000/2/15 20:30:00 */ - t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 7 * day; - offset_day = 7; - offset_sec = 45 * mini; - /* offset_sec = -45 * min;*/ - AssertNotNull(asn_time = - wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec)); - AssertTrue(asn_time->type == asn_utc_time); - XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); - date_str[CTC_DATE_SIZE] = '\0'; - AssertIntEQ(0, XMEMCMP(date_str, "000222211500Z", 13)); - - /* negative offset */ - offset_sec = -45 * mini; - asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); - AssertNotNull(asn_time); - AssertTrue(asn_time->type == asn_utc_time); - XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); - date_str[CTC_DATE_SIZE] = '\0'; - AssertIntEQ(0, XMEMCMP(date_str, "000222194500Z", 13)); - - XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); - XMEMSET(date_str, 0, sizeof(date_str)); - - /* Generalized time will overflow time_t if not long */ -#if !defined(TIME_T_NOT_64BIT) && !defined(NO_64BIT) - s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, - DYNAMIC_TYPE_OPENSSL); - /* GeneralizedTime notation test */ - /* 2055/03/01 09:00:00 */ - t = (time_t)85 * year + 59 * day + 9 * hour + 21 * day; - offset_day = 12; - offset_sec = 10 * mini; - asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); - AssertTrue(asn_time->type == asn_gen_time); - XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); - date_str[CTC_DATE_SIZE] = '\0'; - AssertIntEQ(0, XMEMCMP(date_str, "20550313091000Z", 15)); - - XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); - XMEMSET(date_str, 0, sizeof(date_str)); -#endif /* !TIME_T_NOT_64BIT && !NO_64BIT */ - - /* if WOLFSSL_ASN1_TIME struct is not allocated */ - s = NULL; - - t = (time_t)30 * year + 45 * day + 20 * hour + 30 * mini + 15 + 7 * day; - offset_day = 7; - offset_sec = 45 * mini; - asn_time = wolfSSL_ASN1_TIME_adj(s, t, offset_day, offset_sec); - AssertTrue(asn_time->type == asn_utc_time); - XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); - date_str[CTC_DATE_SIZE] = '\0'; - AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); - XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); - - asn_time = wolfSSL_ASN1_TIME_adj(NULL, t, offset_day, offset_sec); - AssertTrue(asn_time->type == asn_utc_time); - XSTRNCPY(date_str, (const char*)&asn_time->data, CTC_DATE_SIZE); - date_str[CTC_DATE_SIZE] = '\0'; - AssertIntEQ(0, XMEMCMP(date_str, "000222211515Z", 13)); - XFREE(asn_time, NULL, DYNAMIC_TYPE_OPENSSL); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - - -static int test_wolfSSL_ASN1_TIME_to_tm(void) -{ - int res = TEST_SKIPPED; -#if (defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) \ - && !defined(NO_ASN_TIME) - ASN1_TIME asnTime; - struct tm tm; - - XMEMSET(&asnTime, 0, sizeof(ASN1_TIME)); - AssertIntEQ(ASN1_TIME_set_string(&asnTime, "000222211515Z"), 1); - AssertIntEQ(ASN1_TIME_to_tm(&asnTime, &tm), 1); - - AssertIntEQ(tm.tm_sec, 15); - AssertIntEQ(tm.tm_min, 15); - AssertIntEQ(tm.tm_hour, 21); - AssertIntEQ(tm.tm_mday, 22); - AssertIntEQ(tm.tm_mon, 1); - AssertIntEQ(tm.tm_year, 100); - AssertIntEQ(tm.tm_isdst, 0); -#ifdef XMKTIME - AssertIntEQ(tm.tm_wday, 2); - AssertIntEQ(tm.tm_yday, 52); -#endif - - res = TEST_RES_CHECK(1); -#endif - return res; -} static int test_wolfSSL_X509_cmp_time(void) { @@ -39131,13 +41076,17 @@ static int test_wolfSSL_X509_sign2(void) AssertNotNull((der = wolfSSL_X509_get_der(x509, &derSz))); AssertIntEQ(derSz, sizeof(expected)); +#ifndef NO_ASN_TIME AssertIntEQ(XMEMCMP(der, expected, derSz), 0); +#endif wolfSSL_X509_free(ca); wolfSSL_X509_free(x509); wolfSSL_EVP_PKEY_free(priv); +#ifndef NO_ASN_TIME wolfSSL_ASN1_TIME_free(notBefore); wolfSSL_ASN1_TIME_free(notAfter); +#endif res = TEST_RES_CHECK(1); #endif @@ -39148,7 +41097,7 @@ static int test_wolfSSL_X509_sign2(void) static int test_wolfSSL_X509_sign(void) { int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && !defined(NO_ASN_TIME) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_RSA) int ret; char *cn; @@ -39228,7 +41177,7 @@ static int test_wolfSSL_X509_sign(void) #endif /* WOLFSSL_ALT_NAMES */ /* test valid sign case */ - ret = X509_sign(x509, priv, EVP_sha256()); + AssertIntGT(ret = X509_sign(x509, priv, EVP_sha256()), 0); /* test valid X509_sign_ctx case */ AssertNotNull(mctx = EVP_MD_CTX_new()); @@ -40891,29 +42840,6 @@ static int test_wolfSSL_OBJ(void) return res; } -static int test_wolfSSL_i2a_ASN1_OBJECT(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) && !defined(NO_BIO) - ASN1_OBJECT *obj = NULL; - BIO *bio = NULL; - - AssertNotNull(obj = OBJ_nid2obj(NID_sha256)); - AssertTrue((bio = BIO_new(BIO_s_mem())) != NULL); - - AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, obj), 0); - AssertIntGT(wolfSSL_i2a_ASN1_OBJECT(bio, NULL), 0); - - AssertIntEQ(wolfSSL_i2a_ASN1_OBJECT(NULL, obj), 0); - - BIO_free(bio); - ASN1_OBJECT_free(obj); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - static int test_wolfSSL_OBJ_cmp(void) { int res = TEST_SKIPPED; @@ -41050,33 +42976,6 @@ static int test_wolfSSL_OBJ_txt2obj(void) return res; } -static int test_wolfSSL_i2t_ASN1_OBJECT(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && \ - defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) - - char buf[50] = {0}; - ASN1_OBJECT* obj; - const char* oid = "2.5.29.19"; - const char* ln = "X509v3 Basic Constraints"; - - obj = NULL; - AssertIntEQ(i2t_ASN1_OBJECT(NULL, sizeof(buf), obj), WOLFSSL_FAILURE); - AssertIntEQ(i2t_ASN1_OBJECT(buf, sizeof(buf), NULL), WOLFSSL_FAILURE); - AssertIntEQ(i2t_ASN1_OBJECT(buf, 0, NULL), WOLFSSL_FAILURE); - - AssertNotNull(obj = OBJ_txt2obj(oid, 0)); - XMEMSET(buf, 0, sizeof(buf)); - AssertIntEQ(i2t_ASN1_OBJECT(buf, sizeof(buf), obj), XSTRLEN(ln)); - AssertIntEQ(XSTRNCMP(buf, ln, XSTRLEN(ln)), 0); - ASN1_OBJECT_free(obj); - - res = TEST_RES_CHECK(1); -#endif /* OPENSSL_EXTRA && WOLFSSL_CERT_EXT && WOLFSSL_CERT_GEN */ - return res; -} - static int test_wolfSSL_PEM_write_bio_X509(void) { int res = TEST_SKIPPED; @@ -41096,8 +42995,10 @@ static int test_wolfSSL_PEM_write_bio_X509(void) ASN1_TIME* notBeforeA = NULL; ASN1_TIME* notAfterA = NULL; +#ifndef NO_ASN_TIME ASN1_TIME* notBeforeB = NULL; ASN1_TIME* notAfterB = NULL; +#endif int expectedLen; fp = XFOPEN("certs/server-key.pem", "rb"); @@ -41123,6 +43024,7 @@ static int test_wolfSSL_PEM_write_bio_X509(void) expectedLen = 2000; AssertIntEQ(wolfSSL_BIO_get_len(output), expectedLen); +#ifndef NO_ASN_TIME /* read exported X509 PEM back into struct, sanity check on export, * make sure notBefore/notAfter are the same and certs are identical. */ AssertNotNull(PEM_read_bio_X509(output, &x509b, NULL, NULL)); @@ -41132,6 +43034,7 @@ static int test_wolfSSL_PEM_write_bio_X509(void) AssertIntEQ(ASN1_TIME_compare(notAfterA, notAfterB), 0); AssertIntEQ(0, wolfSSL_X509_cmp(x509a, x509b)); X509_free(x509b); +#endif /* Reset output buffer */ BIO_free(output); @@ -42695,7 +44598,7 @@ static int test_wolfSSL_SESSION(void) } #if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ - defined(HAVE_EX_DATA) + defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE) static int clientSessRemCountMalloc = 0; static int serverSessRemCountMalloc = 0; static int clientSessRemCountFree = 0; @@ -42767,7 +44670,7 @@ static int test_wolfSSL_CTX_sess_set_remove_cb(void) { int res = TEST_SKIPPED; #if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ - defined(HAVE_EX_DATA) + defined(HAVE_EX_DATA) && !defined(NO_SESSION_CACHE) /* Check that the remove callback gets called for external data in a * session object */ callback_functions func_cb; @@ -44759,153 +46662,6 @@ static int test_wolfSSL_OPENSSL_hexstr2buf(void) return res; } -static int test_wolfSSL_ASN1_STRING_print_ex(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) -#ifndef NO_BIO - ASN1_STRING* asn_str; - const char data[] = "Hello wolfSSL!"; - ASN1_STRING* esc_str; - const char esc_data[] = "a+;<>"; - BIO *bio; - unsigned long flags; - int p_len; - unsigned char rbuf[255]; - - /* setup */ - XMEMSET(rbuf, 0, 255); - bio = BIO_new(BIO_s_mem()); - BIO_set_write_buf_size(bio,255); - - asn_str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); - ASN1_STRING_set(asn_str, (const void*)data, sizeof(data)); - esc_str = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); - ASN1_STRING_set(esc_str, (const void*)esc_data, sizeof(esc_data)); - - /* no flags */ - XMEMSET(rbuf, 0, 255); - flags = 0; - p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); - AssertIntEQ(p_len, 15); - BIO_read(bio, (void*)rbuf, 15); - AssertStrEQ((char*)rbuf, "Hello wolfSSL!"); - - /* RFC2253 Escape */ - XMEMSET(rbuf, 0, 255); - flags = ASN1_STRFLGS_ESC_2253; - p_len = wolfSSL_ASN1_STRING_print_ex(bio, esc_str, flags); - AssertIntEQ(p_len, 9); - BIO_read(bio, (void*)rbuf, 9); - AssertStrEQ((char*)rbuf, "a\\+\\;\\<\\>"); - - /* Show type */ - XMEMSET(rbuf, 0, 255); - flags = ASN1_STRFLGS_SHOW_TYPE; - p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); - AssertIntEQ(p_len, 28); - BIO_read(bio, (void*)rbuf, 28); - AssertStrEQ((char*)rbuf, "OCTET STRING:Hello wolfSSL!"); - - /* Dump All */ - XMEMSET(rbuf, 0, 255); - flags = ASN1_STRFLGS_DUMP_ALL; - p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); - AssertIntEQ(p_len, 31); - BIO_read(bio, (void*)rbuf, 31); - AssertStrEQ((char*)rbuf, "#48656C6C6F20776F6C6653534C2100"); - - /* Dump Der */ - XMEMSET(rbuf, 0, 255); - flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_DUMP_DER; - p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); - AssertIntEQ(p_len, 35); - BIO_read(bio, (void*)rbuf, 35); - AssertStrEQ((char*)rbuf, "#040F48656C6C6F20776F6C6653534C2100"); - - /* Dump All + Show type */ - XMEMSET(rbuf, 0, 255); - flags = ASN1_STRFLGS_DUMP_ALL | ASN1_STRFLGS_SHOW_TYPE; - p_len = wolfSSL_ASN1_STRING_print_ex(bio, asn_str, flags); - AssertIntEQ(p_len, 44); - BIO_read(bio, (void*)rbuf, 44); - AssertStrEQ((char*)rbuf, "OCTET STRING:#48656C6C6F20776F6C6653534C2100"); - - BIO_free(bio); - ASN1_STRING_free(asn_str); - ASN1_STRING_free(esc_str); - - res = TEST_RES_CHECK(1); -#endif /* !NO_BIO */ -#endif - return res; -} - -static int test_wolfSSL_ASN1_TIME_to_generalizedtime(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN_TIME) - WOLFSSL_ASN1_TIME *t; - WOLFSSL_ASN1_TIME *out; - WOLFSSL_ASN1_TIME *gtime; - int tlen = 0; - unsigned char *data; - - /* UTC Time test */ - AssertNotNull(t = wolfSSL_ASN1_TIME_new()); - XMEMSET(t->data, 0, ASN_GENERALIZED_TIME_SIZE); - AssertNotNull(out = wolfSSL_ASN1_TIME_new()); - t->type = ASN_UTC_TIME; - t->length = ASN_UTC_TIME_SIZE; - XMEMCPY(t->data, "050727123456Z", ASN_UTC_TIME_SIZE); - - tlen = wolfSSL_ASN1_TIME_get_length(t); - AssertIntEQ(tlen, ASN_UTC_TIME_SIZE); - data = wolfSSL_ASN1_TIME_get_data(t); - AssertStrEQ((char*)data, "050727123456Z"); - gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); - AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); - AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); - AssertStrEQ((char*)gtime->data, "20050727123456Z"); - - /* Generalized Time test */ - XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); - XMEMSET(out, 0, ASN_GENERALIZED_TIME_SIZE); - XMEMSET(data, 0, ASN_GENERALIZED_TIME_SIZE); - t->type = ASN_GENERALIZED_TIME; - t->length = ASN_GENERALIZED_TIME_SIZE; - XMEMCPY(t->data, "20050727123456Z", ASN_GENERALIZED_TIME_SIZE); - - tlen = wolfSSL_ASN1_TIME_get_length(t); - AssertIntEQ(tlen, ASN_GENERALIZED_TIME_SIZE); - data = wolfSSL_ASN1_TIME_get_data(t); - AssertStrEQ((char*)data, "20050727123456Z"); - gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, &out); - AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); - AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); - AssertStrEQ((char*)gtime->data, "20050727123456Z"); - XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - /* Null parameter test */ - XMEMSET(t, 0, ASN_GENERALIZED_TIME_SIZE); - gtime = NULL; - out = NULL; - t->type = ASN_UTC_TIME; - t->length = ASN_UTC_TIME_SIZE; - XMEMCPY(t->data, "050727123456Z", ASN_UTC_TIME_SIZE); - AssertNotNull(gtime = wolfSSL_ASN1_TIME_to_generalizedtime(t, NULL)); - AssertIntEQ(gtime->type, ASN_GENERALIZED_TIME); - AssertIntEQ(gtime->length, ASN_GENERALIZED_TIME_SIZE); - AssertStrEQ((char*)gtime->data, "20050727123456Z"); - - XFREE(gtime, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - static int test_wolfSSL_X509_CA_num(void) { int res = TEST_SKIPPED; @@ -44973,7 +46729,8 @@ static int test_wolfSSL_X509_check_ip_asc(void) static int test_wolfSSL_make_cert(void) { int res = TEST_SKIPPED; -#if !defined(NO_RSA) && defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT) +#if !defined(NO_RSA) && !defined(NO_ASN_TIME) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_EXT) int ret; Cert cert; CertName name; @@ -45521,85 +47278,6 @@ static int test_wolfSSL_CRYPTO_cts128(void) } #if defined(OPENSSL_ALL) -#if !defined(NO_ASN) -static int test_wolfSSL_ASN1_STRING_to_UTF8(void) -{ - int res = TEST_SKIPPED; -#if !defined(NO_RSA) - WOLFSSL_X509* x509; - WOLFSSL_X509_NAME* subject; - WOLFSSL_X509_NAME_ENTRY* e; - WOLFSSL_ASN1_STRING* a; - FILE* file; - int idx = 0; - char targetOutput[16] = "www.wolfssl.com"; - unsigned char* actual_output; - int len = 0; - int result = 0; - - AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); - AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); - fclose(file); - - /* wolfSSL_ASN1_STRING_to_UTF8(): NID_commonName */ - AssertNotNull(subject = wolfSSL_X509_get_subject_name(x509)); - AssertIntEQ((idx = wolfSSL_X509_NAME_get_index_by_NID(subject, - NID_commonName, -1)), 5); - AssertNotNull(e = wolfSSL_X509_NAME_get_entry(subject, idx)); - AssertNotNull(a = wolfSSL_X509_NAME_ENTRY_get_data(e)); - AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(&actual_output, a)), 15); - result = strncmp((const char*)actual_output, targetOutput, len); - AssertIntEQ(result, 0); - - /* wolfSSL_ASN1_STRING_to_UTF8(NULL, valid) */ - AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(NULL, a)), - WOLFSSL_FATAL_ERROR); - - /* wolfSSL_ASN1_STRING_to_UTF8(valid, NULL) */ - AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(&actual_output, NULL)), - WOLFSSL_FATAL_ERROR); - - /* wolfSSL_ASN1_STRING_to_UTF8(NULL, NULL) */ - AssertIntEQ((len = wolfSSL_ASN1_STRING_to_UTF8(NULL, NULL)), - WOLFSSL_FATAL_ERROR); - - wolfSSL_X509_free(x509); - XFREE(actual_output, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -static int test_wolfSSL_ASN1_UNIVERSALSTRING_to_string(void) -{ - ASN1_STRING* asn1str_test; - ASN1_STRING* asn1str_answer; - /* Each character is encoded using 4 bytes */ - char input[] = { - 0, 0, 0, 'T', - 0, 0, 0, 'e', - 0, 0, 0, 's', - 0, 0, 0, 't', - }; - char output[] = "Test"; - - AssertNotNull(asn1str_test = ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)); - AssertIntEQ(ASN1_STRING_set(asn1str_test, input, sizeof(input)), 1); - AssertIntEQ(ASN1_UNIVERSALSTRING_to_string(asn1str_test), 1); - - AssertNotNull(asn1str_answer = ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)); - AssertIntEQ(ASN1_STRING_set(asn1str_answer, output, sizeof(output)-1), 1); - - AssertIntEQ(ASN1_STRING_cmp(asn1str_test, asn1str_answer), 0); - - ASN1_STRING_free(asn1str_test); - ASN1_STRING_free(asn1str_answer); - - return TEST_RES_CHECK(1); -} -#endif /* !defined(NO_ASN) */ - static int test_wolfSSL_sk_CIPHER_description(void) { int res = TEST_SKIPPED; @@ -49354,7 +51032,8 @@ static int test_wc_ParseCert_Error(void) static int test_MakeCertWithPathLen(void) { int res = TEST_SKIPPED; -#if defined(WOLFSSL_CERT_REQ) && defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) +#if defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) && \ + defined(WOLFSSL_CERT_GEN) && defined(HAVE_ECC) const byte expectedPathLen = 7; Cert cert; DecodedCert decodedCert; @@ -50371,7 +52050,11 @@ static int test_wolfssl_PKCS7(void) #endif AssertNotNull(bio = BIO_new(BIO_s_mem())); AssertIntEQ(i2d_PKCS7_bio(bio, pkcs7), 1); +#ifndef NO_ASN_TIME AssertIntEQ(i2d_PKCS7(pkcs7, &out), 655); +#else + AssertIntEQ(i2d_PKCS7(pkcs7, &out), 625); +#endif XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); BIO_free(bio); #endif @@ -53922,233 +55605,6 @@ static int test_wolfSSL_X509_NAME_ENTRY_get_object(void) return res; } -static int test_wolfSSL_ASN1_INTEGER_get_set(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) - ASN1_INTEGER *a; - long val; - int ret; - - a = ASN1_INTEGER_new(); - val = 0; - ret = ASN1_INTEGER_set(NULL, val); - AssertIntEQ(ret, 0); - ASN1_INTEGER_free(a); - - /* 0 */ - a = ASN1_INTEGER_new(); - val = 0; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* 40 */ - a = ASN1_INTEGER_new(); - val = 40; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* -40 */ - a = ASN1_INTEGER_new(); - val = -40; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* 128 */ - a = ASN1_INTEGER_new(); - val = 128; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* -128 */ - a = ASN1_INTEGER_new(); - val = -128; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* 200 */ - a = ASN1_INTEGER_new(); - val = 200; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* int max (2147483647) */ - a = ASN1_INTEGER_new(); - val = 2147483647; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - /* int min (-2147483648) */ - a = ASN1_INTEGER_new(); - val = -2147483647 - 1; - ret = ASN1_INTEGER_set(a, val); - AssertIntEQ(ret, 1); - AssertIntEQ(ASN1_INTEGER_get(a), val); - ASN1_INTEGER_free(a); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -#if defined(OPENSSL_EXTRA) -typedef struct ASN1IntTestVector { - const byte* der; - const size_t derSz; - const long value; -} ASN1IntTestVector; -#endif -static int test_wolfSSL_d2i_ASN1_INTEGER(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) - size_t i; - WOLFSSL_ASN1_INTEGER* a = NULL; - WOLFSSL_ASN1_INTEGER* b = NULL; - WOLFSSL_ASN1_INTEGER* c = NULL; - const byte* p = NULL; - byte* reEncoded = NULL; - int reEncodedSz; - - static const byte zeroDer[] = { - 0x02, 0x01, 0x00 - }; - static const byte oneDer[] = { - 0x02, 0x01, 0x01 - }; - static const byte negativeDer[] = { - 0x02, 0x03, 0xC1, 0x16, 0x0D - }; - static const byte positiveDer[] = { - 0x02, 0x03, 0x01, 0x00, 0x01 - }; - static const byte primeDer[] = { - 0x02, 0x82, 0x01, 0x01, 0x00, 0xc0, 0x95, 0x08, 0xe1, 0x57, 0x41, - 0xf2, 0x71, 0x6d, 0xb7, 0xd2, 0x45, 0x41, 0x27, 0x01, 0x65, 0xc6, - 0x45, 0xae, 0xf2, 0xbc, 0x24, 0x30, 0xb8, 0x95, 0xce, 0x2f, 0x4e, - 0xd6, 0xf6, 0x1c, 0x88, 0xbc, 0x7c, 0x9f, 0xfb, 0xa8, 0x67, 0x7f, - 0xfe, 0x5c, 0x9c, 0x51, 0x75, 0xf7, 0x8a, 0xca, 0x07, 0xe7, 0x35, - 0x2f, 0x8f, 0xe1, 0xbd, 0x7b, 0xc0, 0x2f, 0x7c, 0xab, 0x64, 0xa8, - 0x17, 0xfc, 0xca, 0x5d, 0x7b, 0xba, 0xe0, 0x21, 0xe5, 0x72, 0x2e, - 0x6f, 0x2e, 0x86, 0xd8, 0x95, 0x73, 0xda, 0xac, 0x1b, 0x53, 0xb9, - 0x5f, 0x3f, 0xd7, 0x19, 0x0d, 0x25, 0x4f, 0xe1, 0x63, 0x63, 0x51, - 0x8b, 0x0b, 0x64, 0x3f, 0xad, 0x43, 0xb8, 0xa5, 0x1c, 0x5c, 0x34, - 0xb3, 0xae, 0x00, 0xa0, 0x63, 0xc5, 0xf6, 0x7f, 0x0b, 0x59, 0x68, - 0x78, 0x73, 0xa6, 0x8c, 0x18, 0xa9, 0x02, 0x6d, 0xaf, 0xc3, 0x19, - 0x01, 0x2e, 0xb8, 0x10, 0xe3, 0xc6, 0xcc, 0x40, 0xb4, 0x69, 0xa3, - 0x46, 0x33, 0x69, 0x87, 0x6e, 0xc4, 0xbb, 0x17, 0xa6, 0xf3, 0xe8, - 0xdd, 0xad, 0x73, 0xbc, 0x7b, 0x2f, 0x21, 0xb5, 0xfd, 0x66, 0x51, - 0x0c, 0xbd, 0x54, 0xb3, 0xe1, 0x6d, 0x5f, 0x1c, 0xbc, 0x23, 0x73, - 0xd1, 0x09, 0x03, 0x89, 0x14, 0xd2, 0x10, 0xb9, 0x64, 0xc3, 0x2a, - 0xd0, 0xa1, 0x96, 0x4a, 0xbc, 0xe1, 0xd4, 0x1a, 0x5b, 0xc7, 0xa0, - 0xc0, 0xc1, 0x63, 0x78, 0x0f, 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, - 0x32, 0x23, 0x95, 0xa1, 0x77, 0xba, 0x13, 0xd2, 0x97, 0x73, 0xe2, - 0x5d, 0x25, 0xc9, 0x6a, 0x0d, 0xc3, 0x39, 0x60, 0xa4, 0xb4, 0xb0, - 0x69, 0x42, 0x42, 0x09, 0xe9, 0xd8, 0x08, 0xbc, 0x33, 0x20, 0xb3, - 0x58, 0x22, 0xa7, 0xaa, 0xeb, 0xc4, 0xe1, 0xe6, 0x61, 0x83, 0xc5, - 0xd2, 0x96, 0xdf, 0xd9, 0xd0, 0x4f, 0xad, 0xd7 - }; - static const byte garbageDer[] = {0xDE, 0xAD, 0xBE, 0xEF}; - - static const ASN1IntTestVector testVectors[] = { - {zeroDer, sizeof(zeroDer), 0}, - {oneDer, sizeof(oneDer), 1}, - {negativeDer, sizeof(negativeDer), -4123123}, - {positiveDer, sizeof(positiveDer), 65537}, - {primeDer, sizeof(primeDer), 0} - }; - static const size_t NUM_TEST_VECTORS = sizeof(testVectors)/sizeof(testVectors[0]); - - /* Check d2i error conditions */ - /* NULL pointer to input. */ - AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, NULL, 1))); - AssertNull(b); - /* NULL input. */ - AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, 1))); - AssertNull(b); - /* 0 length. */ - p = testVectors[0].der; - AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, 0))); - AssertNull(b); - /* Negative length. */ - p = testVectors[0].der; - AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, -1))); - AssertNull(b); - /* Garbage DER input. */ - p = garbageDer; - AssertNull((a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, sizeof(garbageDer)))); - AssertNull(b); - - { - /* Check i2d error conditions */ - /* NULL input. */ - byte* p2 = NULL; - AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(NULL, &p2), 0); - /* 0 length input data buffer (a->length == 0). */ - AssertNotNull((a = wolfSSL_ASN1_INTEGER_new())); - AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(a, &p2), 0); - a->data = NULL; - /* NULL input data buffer. */ - AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(a, &p2), 0); - /* Reset a->data. */ - a->data = a->intData; - /* Set a to valid value. */ - AssertIntEQ(wolfSSL_ASN1_INTEGER_set(a, 1), WOLFSSL_SUCCESS); - /* NULL output buffer. */ - AssertIntLT(wolfSSL_i2d_ASN1_INTEGER(a, NULL), 0); - wolfSSL_ASN1_INTEGER_free(a); - } - - for (i = 0; i < NUM_TEST_VECTORS; ++i) { - p = testVectors[i].der; - a = wolfSSL_d2i_ASN1_INTEGER(&b, &p, testVectors[i].derSz); - AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, b), 0); - - if (testVectors[i].derSz <= sizeof(long)) { - c = wolfSSL_ASN1_INTEGER_new(); - wolfSSL_ASN1_INTEGER_set(c, testVectors[i].value); - AssertIntEQ(wolfSSL_ASN1_INTEGER_cmp(a, c), 0); - wolfSSL_ASN1_INTEGER_free(c); - } - - /* Convert to DER without a pre-allocated output buffer. */ - AssertIntGT((reEncodedSz = wolfSSL_i2d_ASN1_INTEGER(a, &reEncoded)), 0); - AssertIntEQ(reEncodedSz, testVectors[i].derSz); - AssertIntEQ(XMEMCMP(reEncoded, testVectors[i].der, reEncodedSz), 0); - - /* Convert to DER with a pre-allocated output buffer. In this case, the - * output buffer pointer should be incremented just past the end of the - * encoded data. */ - p = reEncoded; - AssertIntGT((reEncodedSz = wolfSSL_i2d_ASN1_INTEGER(a, &reEncoded)), 0); - AssertIntEQ(reEncodedSz, testVectors[i].derSz); - AssertPtrEq(p, reEncoded - reEncodedSz); - AssertIntEQ(XMEMCMP(p, testVectors[i].der, reEncodedSz), 0); - - XFREE(reEncoded - reEncodedSz, NULL, DYNAMIC_TYPE_ASN1); - reEncoded = NULL; - wolfSSL_ASN1_INTEGER_free(a); - } - - res = TEST_RES_CHECK(1); -#endif /* OPENSSL_EXTRA */ - return res; -} - static int test_wolfSSL_X509_STORE_get1_certs(void) { int res = TEST_SKIPPED; @@ -54200,189 +55656,6 @@ static int test_wolfSSL_X509_STORE_get1_certs(void) return res; } -/* Testing code used in dpp.c in hostap */ -#if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) -typedef struct { - /* AlgorithmIdentifier ecPublicKey with optional parameters present - * as an OID identifying the curve */ - X509_ALGOR *alg; - /* Compressed format public key per ANSI X9.63 */ - ASN1_BIT_STRING *pub_key; -} DPP_BOOTSTRAPPING_KEY; - -ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { - ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), - ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) -} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY) - -IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY) -#endif - -static int test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS(void) -{ - int res = TEST_SKIPPED; - /* Testing code used in dpp.c in hostap */ -#if defined(OPENSSL_ALL) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) - EC_KEY *eckey; - EVP_PKEY *key; - size_t len; - unsigned char *der = NULL; - DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; - const unsigned char *in = ecc_clikey_der_256; - const EC_GROUP *group; - const EC_POINT *point; - int nid; - - AssertNotNull(bootstrap = DPP_BOOTSTRAPPING_KEY_new()); - - AssertNotNull(key = d2i_PrivateKey(EVP_PKEY_EC, NULL, &in, - (long)sizeof_ecc_clikey_der_256)); - AssertNotNull(eckey = EVP_PKEY_get1_EC_KEY(key)); - AssertNotNull(group = EC_KEY_get0_group(eckey)); - AssertNotNull(point = EC_KEY_get0_public_key(eckey)); - nid = EC_GROUP_get_curve_name(group); - - AssertIntEQ(X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), - V_ASN1_OBJECT, OBJ_nid2obj(nid)), 1); - AssertIntEQ(EC_POINT_point2oct(group, point, 0, NULL, 0, NULL), 0); -#ifdef HAVE_COMP_KEY - AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - NULL, 0, NULL)), 0); -#else - AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, - NULL, 0, NULL)), 0); -#endif - AssertNotNull(der = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1)); -#ifdef HAVE_COMP_KEY - AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - der, len-1, NULL), 0); - AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - der, len, NULL), len); -#else - AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, - der, len-1, NULL), 0); - AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, - der, len, NULL), len); -#endif - bootstrap->pub_key->data = der; - bootstrap->pub_key->length = (int)len; - /* Not actually used */ - bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; - - der = NULL; - AssertIntGT(i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der), 0); - - XFREE(der, NULL, DYNAMIC_TYPE_ASN1); - EVP_PKEY_free(key); - EC_KEY_free(eckey); - DPP_BOOTSTRAPPING_KEY_free(bootstrap); - - res = TEST_RES_CHECK(1); -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* WOLFSSL_WPAS && HAVE_ECC && USE_CERT_BUFFERS_256 */ - return res; -} - -static int test_wolfSSL_i2c_ASN1_INTEGER(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) - ASN1_INTEGER *a; - unsigned char *pp,*tpp; - int ret; - - - a = wolfSSL_ASN1_INTEGER_new(); - - /* 40 */ - a->intData[0] = ASN_INTEGER; - a->intData[1] = 1; - a->intData[2] = 40; - ret = i2c_ASN1_INTEGER(a, NULL); - AssertIntEQ(ret, 1); - AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER)); - tpp = pp; - XMEMSET(pp, 0, ret + 1); - i2c_ASN1_INTEGER(a, &pp); - pp--; - AssertIntEQ(*pp, 40); - XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - /* 128 */ - a->intData[0] = ASN_INTEGER; - a->intData[1] = 1; - a->intData[2] = 128; - ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); - AssertIntEQ(ret, 2); - AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER)); - tpp = pp; - XMEMSET(pp, 0, ret + 1); - wolfSSL_i2c_ASN1_INTEGER(a, &pp); - pp--; - AssertIntEQ(*(pp--), 128); - AssertIntEQ(*pp, 0); - XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - /* -40 */ - a->intData[0] = ASN_INTEGER; - a->intData[1] = 1; - a->intData[2] = 40; - a->negative = 1; - ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); - AssertIntEQ(ret, 1); - AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER)); - tpp = pp; - XMEMSET(pp, 0, ret + 1); - wolfSSL_i2c_ASN1_INTEGER(a, &pp); - pp--; - AssertIntEQ(*pp, 216); - XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - /* -128 */ - a->intData[0] = ASN_INTEGER; - a->intData[1] = 1; - a->intData[2] = 128; - a->negative = 1; - ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); - AssertIntEQ(ret, 1); - AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER)); - tpp = pp; - XMEMSET(pp, 0, ret + 1); - wolfSSL_i2c_ASN1_INTEGER(a, &pp); - pp--; - AssertIntEQ(*pp, 128); - XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - /* -200 */ - a->intData[0] = ASN_INTEGER; - a->intData[1] = 1; - a->intData[2] = 200; - a->negative = 1; - ret = wolfSSL_i2c_ASN1_INTEGER(a, NULL); - AssertIntEQ(ret, 2); - AssertNotNull(pp = (unsigned char*)XMALLOC(ret + 1, NULL, - DYNAMIC_TYPE_TMP_BUFFER)); - tpp = pp; - XMEMSET(pp, 0, ret + 1); - wolfSSL_i2c_ASN1_INTEGER(a, &pp); - pp--; - AssertIntEQ(*(pp--), 56); - AssertIntEQ(*pp, 255); - - XFREE(tpp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - wolfSSL_ASN1_INTEGER_free(a); - - res = TEST_RES_CHECK(1); -#endif /* OPENSSL_EXTRA && !NO_ASN */ - return res; -} - /* include misc.c here regardless of NO_INLINE, because misc.c implementations * have default (hidden) visibility, and in the absence of visibility, it's * benign to mask out the library implementation. @@ -54444,6 +55717,9 @@ static int test_wolfSSL_X509_print(void) #if defined(WC_DISABLE_RADIX_ZERO_PAD) /* Will print IP address subject alt name. */ AssertIntEQ(BIO_get_mem_data(bio, NULL), 3349); + #elif defined(NO_ASN_TIME) + /* Will print IP address subject alt name but not Validity. */ + AssertIntEQ(BIO_get_mem_data(bio, NULL), 3235); #else /* Will print IP address subject alt name. */ AssertIntEQ(BIO_get_mem_data(bio, NULL), 3350); @@ -54529,123 +55805,8 @@ static int test_wolfSSL_BIO_get_len(void) return res; } -static int test_wolfSSL_ASN1_STRING_print(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_ALL) && !defined(NO_ASN) && !defined(NO_CERTS) - ASN1_STRING* asnStr = NULL; - const char HELLO_DATA[]= \ - {'H','e','l','l','o',' ','w','o','l','f','S','S','L','!'}; - #define MAX_UNPRINTABLE_CHAR 32 - #define MAX_BUF 255 - unsigned char unprintableData[MAX_UNPRINTABLE_CHAR + sizeof(HELLO_DATA)]; - unsigned char expected[sizeof(unprintableData)+1]; - unsigned char rbuf[MAX_BUF]; - - BIO *bio; - int p_len, i; - - /* setup */ - - for (i = 0; i < (int)sizeof(HELLO_DATA); i++) { - unprintableData[i] = HELLO_DATA[i]; - expected[i] = HELLO_DATA[i]; - } - - for (i = 0; i < (int)MAX_UNPRINTABLE_CHAR; i++) { - unprintableData[sizeof(HELLO_DATA)+i] = i; - - if (i == (int)'\n' || i == (int)'\r') - expected[sizeof(HELLO_DATA)+i] = i; - else - expected[sizeof(HELLO_DATA)+i] = '.'; - } - - unprintableData[sizeof(unprintableData)-1] = '\0'; - expected[sizeof(expected)-1] = '\0'; - - XMEMSET(rbuf, 0, MAX_BUF); - bio = BIO_new(BIO_s_mem()); - BIO_set_write_buf_size(bio, MAX_BUF); - - asnStr = ASN1_STRING_type_new(V_ASN1_OCTET_STRING); - ASN1_STRING_set(asnStr,(const void*)unprintableData, - (int)sizeof(unprintableData)); - /* test */ - p_len = wolfSSL_ASN1_STRING_print(bio, asnStr); - AssertIntEQ(p_len, 46); - BIO_read(bio, (void*)rbuf, 46); - - AssertStrEQ((char*)rbuf, (const char*)expected); - - BIO_free(bio); - ASN1_STRING_free(asnStr); - - res = TEST_RES_CHECK(1); -#endif /* OPENSSL_EXTRA && !NO_ASN && !NO_CERTS */ - return res; -} - #endif /* !NO_BIO */ -static int test_wolfSSL_ASN1_get_object(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) - const unsigned char* derBuf = cliecc_cert_der_256; - int len = sizeof_cliecc_cert_der_256; - long asnLen = 0; - int tag = 0, cls = 0; - ASN1_OBJECT *a; - - /* Read a couple TLV triplets and make sure they match the expected values */ - - AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, len) & 0x80, 0); - AssertIntEQ(asnLen, 862); - AssertIntEQ(tag, 0x10); - AssertIntEQ(cls, 0); - - AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, - len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); - AssertIntEQ(asnLen, 772); - AssertIntEQ(tag, 0x10); - AssertIntEQ(cls, 0); - - AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, - len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); - AssertIntEQ(asnLen, 3); - AssertIntEQ(tag, 0); - AssertIntEQ(cls, 0x80); - - AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, - len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); - AssertIntEQ(asnLen, 1); - AssertIntEQ(tag, 0x2); - AssertIntEQ(cls, 0); - derBuf += asnLen; - - AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, - len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); - AssertIntEQ(asnLen, 20); - AssertIntEQ(tag, 0x2); - AssertIntEQ(cls, 0); - derBuf += asnLen; - - AssertIntEQ(ASN1_get_object(&derBuf, &asnLen, &tag, &cls, - len - (derBuf - cliecc_cert_der_256)) & 0x80, 0); - AssertIntEQ(asnLen, 10); - AssertIntEQ(tag, 0x10); - AssertIntEQ(cls, 0); - - /* Read an ASN OBJECT */ - AssertNotNull(d2i_ASN1_OBJECT(&a, &derBuf, len)); - ASN1_OBJECT_free(a); - - res = TEST_RES_CHECK(1); -#endif /* OPENSSL_EXTRA && HAVE_ECC && USE_CERT_BUFFERS_256 */ - return res; -} - static int test_wolfSSL_RSA(void) { int res = TEST_SKIPPED; @@ -63671,6 +64832,40 @@ TEST_CASE testCases[] = { /* Multicast */ TEST_DECL(test_wolfSSL_mcast), + /* ASN.1 compatibility API tests */ + TEST_DECL(test_wolfSSL_ASN1_BIT_STRING), + TEST_DECL(test_wolfSSL_ASN1_INTEGER), + TEST_DECL(test_wolfSSL_ASN1_INTEGER_cmp), + TEST_DECL(test_wolfSSL_ASN1_INTEGER_BN), + TEST_DECL(test_wolfSSL_ASN1_INTEGER_get_set), + TEST_DECL(test_wolfSSL_d2i_ASN1_INTEGER), + TEST_DECL(test_wolfSSL_a2i_ASN1_INTEGER), + TEST_DECL(test_wolfSSL_i2c_ASN1_INTEGER), + TEST_DECL(test_wolfSSL_ASN1_OBJECT), + TEST_DECL(test_wolfSSL_ASN1_get_object), + TEST_DECL(test_wolfSSL_i2a_ASN1_OBJECT), + TEST_DECL(test_wolfSSL_i2t_ASN1_OBJECT), + TEST_DECL(test_wolfSSL_sk_ASN1_OBJECT), + TEST_DECL(test_wolfSSL_ASN1_STRING), + TEST_DECL(test_wolfSSL_ASN1_STRING_to_UTF8), + TEST_DECL(test_wolfSSL_i2s_ASN1_STRING), + TEST_DECL(test_wolfSSL_ASN1_STRING_canon), + TEST_DECL(test_wolfSSL_ASN1_STRING_print), + TEST_DECL(test_wolfSSL_ASN1_STRING_print_ex), + TEST_DECL(test_wolfSSL_ASN1_UNIVERSALSTRING_to_string), + TEST_DECL(test_wolfSSL_ASN1_GENERALIZEDTIME_free), + TEST_DECL(test_wolfSSL_ASN1_GENERALIZEDTIME_print), + TEST_DECL(test_wolfSSL_ASN1_TIME), + TEST_DECL(test_wolfSSL_ASN1_TIME_to_string), + TEST_DECL(test_wolfSSL_ASN1_TIME_diff_compare), + TEST_DECL(test_wolfSSL_ASN1_TIME_adj), + TEST_DECL(test_wolfSSL_ASN1_TIME_to_tm), + TEST_DECL(test_wolfSSL_ASN1_TIME_to_generalizedtime), + TEST_DECL(test_wolfSSL_ASN1_TIME_print), + TEST_DECL(test_wolfSSL_ASN1_UTCTIME_print), + TEST_DECL(test_wolfSSL_ASN1_TYPE), + TEST_DECL(test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS), + /* compatibility tests */ TEST_DECL(test_wolfSSL_lhash), TEST_DECL(test_wolfSSL_X509_NAME), @@ -63687,10 +64882,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_DES), TEST_DECL(test_wolfSSL_certs), TEST_DECL(test_wolfSSL_X509_check_private_key), - TEST_DECL(test_wolfSSL_ASN1_TIME_print), - TEST_DECL(test_wolfSSL_ASN1_UTCTIME_print), - TEST_DECL(test_wolfSSL_ASN1_TIME_diff_compare), - TEST_DECL(test_wolfSSL_ASN1_GENERALIZEDTIME_free), TEST_DECL(test_wolfSSL_private_keys), TEST_DECL(test_wolfSSL_PEM_read_PrivateKey), #ifndef NO_BIO @@ -63796,9 +64987,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_PEM_read_bio), TEST_DECL(test_wolfSSL_BIO), #endif - TEST_DECL(test_wolfSSL_ASN1_STRING), - TEST_DECL(test_wolfSSL_ASN1_BIT_STRING), - TEST_DECL(test_wolfSSL_a2i_ASN1_INTEGER), TEST_DECL(test_wolfSSL_a2i_IPADDRESS), TEST_DECL(test_wolfSSL_X509), TEST_DECL(test_wolfSSL_X509_VERIFY_PARAM), @@ -63816,8 +65004,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_RAND), TEST_DECL(test_wolfSSL_BUF), TEST_DECL(test_wolfSSL_set_tlsext_status_type), - TEST_DECL(test_wolfSSL_ASN1_TIME_adj), - TEST_DECL(test_wolfSSL_ASN1_TIME_to_tm), TEST_DECL(test_wolfSSL_X509_cmp_time), TEST_DECL(test_wolfSSL_X509_time_adj), TEST_DECL(test_wolfSSL_CTX_set_client_CA_list), @@ -63844,11 +65030,9 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_HMAC), TEST_DECL(test_wolfSSL_CMAC), TEST_DECL(test_wolfSSL_OBJ), - TEST_DECL(test_wolfSSL_i2a_ASN1_OBJECT), TEST_DECL(test_wolfSSL_OBJ_cmp), TEST_DECL(test_wolfSSL_OBJ_txt2nid), TEST_DECL(test_wolfSSL_OBJ_txt2obj), - TEST_DECL(test_wolfSSL_i2t_ASN1_OBJECT), TEST_DECL(test_wolfSSL_PEM_write_bio_X509), TEST_DECL(test_wolfSSL_X509_NAME_ENTRY), TEST_DECL(test_wolfSSL_X509_set_name), @@ -63904,12 +65088,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_X509_NAME_ENTRY_get_object), TEST_DECL(test_wolfSSL_OpenSSL_add_all_algorithms), TEST_DECL(test_wolfSSL_OPENSSL_hexstr2buf), - TEST_DECL(test_wolfSSL_ASN1_STRING_print_ex), - TEST_DECL(test_wolfSSL_ASN1_TIME_to_generalizedtime), - TEST_DECL(test_wolfSSL_ASN1_INTEGER_get_set), - TEST_DECL(test_wolfSSL_d2i_ASN1_INTEGER), - TEST_DECL(test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS), - TEST_DECL(test_wolfSSL_i2c_ASN1_INTEGER), TEST_DECL(test_wolfSSL_X509_check_ca), TEST_DECL(test_wolfSSL_X509_check_ip_asc), TEST_DECL(test_wolfSSL_make_cert), @@ -63948,8 +65126,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_X509_PUBKEY_get), TEST_DECL(test_wolfSSL_sk_CIPHER_description), TEST_DECL(test_wolfSSL_get_ciphers_compat), - TEST_DECL(test_wolfSSL_ASN1_STRING_to_UTF8), - TEST_DECL(test_wolfSSL_ASN1_UNIVERSALSTRING_to_string), TEST_DECL(test_wolfSSL_EVP_PKEY_set1_get1_DSA), TEST_DECL(test_wolfSSL_DSA_SIG), TEST_DECL(test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY), @@ -64084,10 +65260,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_X509_EXTENSION_get_critical), TEST_DECL(test_wolfSSL_X509V3_EXT_print), TEST_DECL(test_wolfSSL_X509_cmp), -#ifndef NO_BIO - TEST_DECL(test_wolfSSL_ASN1_STRING_print), -#endif - TEST_DECL(test_wolfSSL_ASN1_get_object), TEST_DECL(test_openssl_generate_key_and_cert), TEST_DECL(test_wolfSSL_CRYPTO_memcmp), TEST_DECL(test_wolfSSL_read_detect_TCP_disconnect), diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 90e376a05..ddae9aff7 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -13657,31 +13657,27 @@ int GetFormattedTime(void* currTime, byte* buf, word32 len) if (ts->tm_year >= 50 && ts->tm_year < 100) { year = ts->tm_year; } - else if (ts->tm_year >= 100 && ts->tm_year < 150) { - year = ts->tm_year - 100; - } else { - WOLFSSL_MSG("unsupported year range"); - return BAD_FUNC_ARG; + year = ts->tm_year - 100; } mon = ts->tm_mon + 1; day = ts->tm_mday; hour = ts->tm_hour; mini = ts->tm_min; sec = ts->tm_sec; - #if defined(WOLF_C89) - if (len < 14) { - WOLFSSL_MSG("buffer for GetFormattedTime is too short."); - return BUFFER_E; - } - ret = XSPRINTF((char*)buf, + #if defined(WOLF_C89) + if (len < ASN_UTC_TIME_SIZE) { + WOLFSSL_MSG("buffer for GetFormattedTime is too short."); + return BUFFER_E; + } + ret = XSPRINTF((char*)buf, "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); - #else - ret = XSNPRINTF((char*)buf, len, + #else + ret = XSNPRINTF((char*)buf, len, "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); - #endif + #endif } else { /* GeneralizedTime */ @@ -13691,19 +13687,19 @@ int GetFormattedTime(void* currTime, byte* buf, word32 len) hour = ts->tm_hour; mini = ts->tm_min; sec = ts->tm_sec; - #if defined(WOLF_C89) - if (len < 16) { - WOLFSSL_MSG("buffer for GetFormattedTime is too short."); - return BUFFER_E; - } - ret = XSPRINTF((char*)buf, + #if defined(WOLF_C89) + if (len < ASN_GENERALIZED_TIME_SIZE) { + WOLFSSL_MSG("buffer for GetFormattedTime is too short."); + return BUFFER_E; + } + ret = XSPRINTF((char*)buf, "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); - #else - ret = XSNPRINTF((char*)buf, len, + #else + ret = XSNPRINTF((char*)buf, len, "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); - #endif + #endif } return ret; @@ -14630,48 +14626,58 @@ word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) int sz; int ret = 0; int o = 0; + const byte* algoName = 0; + word32 algoSz = 0; CALLOC_ASNSETDATA(dataASN, algoIdASN_Length, ret, NULL); - /* Set the OID and OID type to encode. */ - SetASN_OID(&dataASN[ALGOIDASN_IDX_OID], algoOID, type); - /* Hashes, signatures not ECC and keys not RSA put put NULL tag. */ - if (!(type == oidHashType || - (type == oidSigType && !IsSigAlgoECC(algoOID)) || - (type == oidKeyType && algoOID == RSAk))) { - /* Don't put out NULL DER item. */ - dataASN[ALGOIDASN_IDX_NULL].noOut = 1; - } - if (algoOID == DSAk) { - /* Don't include SEQUENCE for DSA keys. */ - o = 1; - } - else if (curveSz > 0) { - /* Don't put out NULL DER item. */ - dataASN[ALGOIDASN_IDX_NULL].noOut = 0; - /* Include space for extra data of length curveSz. - * Subtract 1 for sequence and 1 for length encoding. */ - SetASN_Buffer(&dataASN[ALGOIDASN_IDX_NULL], NULL, curveSz - 2); - } - - /* Calculate size of encoding. */ - ret = SizeASN_Items(algoIdASN + o, dataASN + o, algoIdASN_Length - o, &sz); - if (ret == 0 && output != NULL) { - /* Encode into buffer. */ - SetASN_Items(algoIdASN + o, dataASN + o, algoIdASN_Length - o, output); - if (curveSz > 0) { - /* Return size excluding curve data. */ - sz = dataASN[o].offset - dataASN[ALGOIDASN_IDX_NULL].offset; - } - } - - if (ret == 0) { - /* Return encoded size. */ - ret = sz; + algoName = OidFromId(algoOID, type, &algoSz); + if (algoName == NULL) { + WOLFSSL_MSG("Unknown Algorithm"); } else { - /* Unsigned return type so 0 indicates error. */ - ret = 0; + /* Set the OID and OID type to encode. */ + SetASN_OID(&dataASN[ALGOIDASN_IDX_OID], algoOID, type); + /* Hashes, signatures not ECC and keys not RSA output NULL tag. */ + if (!(type == oidHashType || + (type == oidSigType && !IsSigAlgoECC(algoOID)) || + (type == oidKeyType && algoOID == RSAk))) { + /* Don't put out NULL DER item. */ + dataASN[ALGOIDASN_IDX_NULL].noOut = 1; + } + if (algoOID == DSAk) { + /* Don't include SEQUENCE for DSA keys. */ + o = 1; + } + else if (curveSz > 0) { + /* Don't put out NULL DER item. */ + dataASN[ALGOIDASN_IDX_NULL].noOut = 0; + /* Include space for extra data of length curveSz. + * Subtract 1 for sequence and 1 for length encoding. */ + SetASN_Buffer(&dataASN[ALGOIDASN_IDX_NULL], NULL, curveSz - 2); + } + + /* Calculate size of encoding. */ + ret = SizeASN_Items(algoIdASN + o, dataASN + o, algoIdASN_Length - o, + &sz); + if (ret == 0 && output != NULL) { + /* Encode into buffer. */ + SetASN_Items(algoIdASN + o, dataASN + o, algoIdASN_Length - o, + output); + if (curveSz > 0) { + /* Return size excluding curve data. */ + sz = dataASN[o].offset - dataASN[ALGOIDASN_IDX_NULL].offset; + } + } + + if (ret == 0) { + /* Return encoded size. */ + ret = sz; + } + else { + /* Unsigned return type so 0 indicates error. */ + ret = 0; + } } FREE_ASNSETDATA(dataASN, NULL); @@ -35913,6 +35919,9 @@ end: word32 lastDateSz = MAX_DATE_SIZE; word32 nextDateSz = MAX_DATE_SIZE; + /* When NO_ASN_TIME is defined, verify not used. */ + (void)verify; + WOLFSSL_MSG("ParseCRL"); CALLOC_ASNGETDATA(dataASN, crlASN_Length, ret, dcrl->heap); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index b9e164fb1..e98e80804 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -6249,6 +6249,11 @@ WOLFSSL_LOCAL int CreateCookieExt(const WOLFSSL* ssl, byte* hash, WOLFSSL_LOCAL int TranslateErrorToAlert(int err); +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +void* wolfssl_sk_pop_type(WOLFSSL_STACK* sk, WOLF_STACK_TYPE type); +WOLFSSL_STACK* wolfssl_sk_new_type(WOLF_STACK_TYPE type); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index cbae873b5..f9c20d1f9 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -228,7 +228,7 @@ typedef struct WOLFSSL_DIST_POINT WOLFSSL_DIST_POINT; typedef struct WOLFSSL_CONF_CTX WOLFSSL_CONF_CTX; -#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +#if defined(OPENSSL_EXTRA) struct WOLFSSL_OBJ_NAME { int type; @@ -245,7 +245,7 @@ struct WOLFSSL_BASIC_CONSTRAINTS { WOLFSSL_ASN1_INTEGER *pathlen; }; -#endif /* OPENSSL_ALL || OPENSSL_EXTRA*/ +#endif /* OPENSSL_EXTRA*/ #define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME #define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME @@ -326,8 +326,7 @@ struct WOLFSSL_ASN1_OBJECT { int grp; /* type of OID, i.e. oidCertPolicyType */ int nid; unsigned int objSz; -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \ - defined(WOLFSSL_APACHE_HTTPD) +#if defined(OPENSSL_EXTRA) int ca; WOLFSSL_ASN1_INTEGER *pathlen; #endif @@ -342,7 +341,7 @@ struct WOLFSSL_ASN1_OBJECT { WOLFSSL_ASN1_STRING* dNSName; WOLFSSL_ASN1_STRING ia5_internal; WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */ -#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) +#if defined(OPENSSL_ALL) WOLFSSL_ASN1_STRING* uniformResourceIdentifier; WOLFSSL_ASN1_STRING iPAddress_internal; WOLFSSL_ASN1_OTHERNAME* otherName; /* added for Apache httpd */ @@ -5032,8 +5031,8 @@ WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT * WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag); WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags); WOLFSSL_API int wolfSSL_ASN1_STRING_print(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str); -WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t); -WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(const WOLFSSL_ASN1_TIME *t); +WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(const WOLFSSL_ASN1_TIME *t); WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, WOLFSSL_ASN1_TIME **out); WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 90391496c..560d888d0 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -116,6 +116,7 @@ enum ASN_Tags { ASN_APPLICATION = 0x40, ASN_CONTEXT_SPECIFIC = 0x80, ASN_PRIVATE = 0xC0, + ASN_CLASS_MASK = 0xC0, CRL_EXTENSIONS = 0xa0, ASN_EXTENSIONS = 0xa3, diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 92fa6edce..7ba03c0b7 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -315,8 +315,8 @@ typedef struct WOLFSSL_ASN1_INTEGER { unsigned int dataMax; /* max size of data buffer */ unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ - int length; - int type; + int length; /* Length of DER encoding. */ + int type; /* ASN.1 type. Includes negative flag. */ } WOLFSSL_ASN1_INTEGER; diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index cc219b227..82a03fa4a 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2700,6 +2700,13 @@ extern void uITRON4_free(void *p) ; #define NO_SESSION_CACHE #endif +#if defined(NO_ASN_TIME) && !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB) + #define WOLFSSL_NO_DEF_TICKET_ENC_CB +#endif +#if defined(NO_ASN_TIME) && defined(HAVE_SESSION_TICKET) + #undef HAVE_SESSION_TICKET +#endif + /* Use static ECC structs for Position Independent Code (PIC) */ #if defined(__IAR_SYSTEMS_ICC__) && defined(__ROPI__) #define WOLFSSL_ECC_CURVE_STATIC