diff --git a/doc/dox_comments/header_files/ssl.h b/doc/dox_comments/header_files/ssl.h index d0c6cb555..1eed09aec 100644 --- a/doc/dox_comments/header_files/ssl.h +++ b/doc/dox_comments/header_files/ssl.h @@ -11363,6 +11363,33 @@ WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp); */ WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); +/*! + \ingroup CertsKeys + + \brief This function looks for and returns the extension index + matching the passed in NID value. + + \return >= 0 If successful the extension index is returned. + \return -1 If extension is not found or error is encountered. + + \param x509 certificate to get parse through for extension. + \param nid extension OID to be found. + \param lastPos start search from extension after lastPos. + Set to -1 initially. + + _Example_ + \code + const WOLFSSL_X509* x509; + int lastPos = -1; + int idx; + + idx = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, lastPos); + \endcode + +*/ +WOLFSSL_API int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, + int nid, int lastPos); + /*! \ingroup CertsKeys diff --git a/src/internal.c b/src/internal.c index 08f57bf8c..fb790d1ad 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3283,6 +3283,24 @@ void FreeX509(WOLFSSL_X509* x509) XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); x509->authInfo = NULL; } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + if (x509->authInfoCaIssuer != NULL) { + XFREE(x509->authInfoCaIssuer, x509->heap, DYNAMIC_TYPE_X509_EXT); + } + if (x509->notBeforeTime != NULL) { + XFREE(x509->notBeforeTime, x509->heap, DYNAMIC_TYPE_OPENSSL); + } + if (x509->notAfterTime != NULL) { + XFREE(x509->notAfterTime, x509->heap, DYNAMIC_TYPE_OPENSSL); + } + if (x509->ext_sk != NULL) { + wolfSSL_sk_X509_EXTENSION_free(x509->ext_sk); + } + /* Free serialNumber that was set by wolfSSL_X509_get_serialNumber */ + if (x509->serialNumber != NULL) { + wolfSSL_ASN1_INTEGER_free(x509->serialNumber); + } + #endif /* OPENSSL_ALL || WOLFSSL_QT */ if (x509->extKeyUsageSrc != NULL) { XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); x509->extKeyUsageSrc= NULL; diff --git a/src/ssl.c b/src/ssl.c index 6d6a682a6..237d7cb8e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -7289,6 +7289,1025 @@ int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passedCert) return extCount; } +/* Creates and returns pointer to a new X509_EXTENSION object in memory */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_new"); + + WOLFSSL_X509_EXTENSION* newExt; + newExt = (WOLFSSL_X509_EXTENSION*)XMALLOC(sizeof(WOLFSSL_X509_EXTENSION), + NULL, DYNAMIC_TYPE_X509_EXT); + if (newExt == NULL) + return NULL; + XMEMSET(newExt, 0, sizeof(WOLFSSL_X509_EXTENSION)); + + return newExt; +} + +void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* x) +{ + WOLFSSL_ASN1_STRING asn1; + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_free"); + if (x == NULL) + return; + + if (x->obj != NULL) + wolfSSL_ASN1_OBJECT_free(x->obj); + + asn1 = x->value; + if (asn1.length > 0 && asn1.data != NULL && asn1.isDynamic) + XFREE(asn1.data, NULL, DYNAMIC_TYPE_OPENSSL); + + wolfSSL_sk_ASN1_OBJECT_free(x->ext_sk); + + XFREE(x, NULL, DYNAMIC_TYPE_X509_EXT); +} + +/* Creates and returns a new WOLFSSL_CIPHER stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void) +{ + WOLFSSL_STACK* sk = NULL; + WOLFSSL_ENTER("wolfSSL_sk_new_x509_ext"); + + sk = wolfSSL_sk_new_null(); + if (sk == NULL) + return NULL; + sk->type = STACK_TYPE_X509_EXT; + + return sk; +} + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk,WOLFSSL_X509_EXTENSION* ext) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_push"); + + if (sk == NULL || ext == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.ext == NULL) { + sk->data.ext = ext; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.ext = sk->data.ext; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.ext = ext; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + +/* Free the structure for X509_EXTENSION stack + * + * sk stack to free nodes in + */ +void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_EXTENSION_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while ((node != NULL) && (sk->num > 1)) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_X509_EXTENSION_free(tmp->data.ext); + XFREE(tmp, NULL, DYNAMIC_TYPE_X509); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_X509_EXTENSION_free(sk->data.ext); + } + XFREE(sk, NULL, DYNAMIC_TYPE_X509); +} + +/* Gets the X509_EXTENSION* ext based on it's location in WOLFSSL_X509* x509. + * + * x509 : The X509 structure to look for the extension. + * loc : Location of the extension. If the extension is found at the given + * location, a new X509_EXTENSION structure is populated with extension-specific + * data based on the extension type. + + * Returns NULL on error or pointer to X509_EXTENSION structure containing the + * extension. The returned X509_EXTENSION should not be free'd by caller. + * The returned X509_EXTENSION is pushed onto a stack inside the x509 argument. + * This is later free'd when x509 is free'd. + * + * NOTE: for unknown extension NIDs, a X509_EXTENSION is populated with the + * extension oid as the ASN1_OBJECT (QT compatibility) + */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x509, int loc) +{ + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ENTER("wolfSSL_X509_get_ext"); + if (x509 == NULL) + return NULL; + + ext = wolfSSL_X509_set_ext((WOLFSSL_X509*) x509, loc); + return ext; +} + +/* Pushes a new X509_EXTENSION* ext onto the stack inside WOLFSSL_X509* x509. + * This is currently a helper function for wolfSSL_X509_get_ext + * Caller does not free the returned WOLFSSL_X509_EXTENSION* + */ +WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x509, int loc) +{ + int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0; + int objSz = 0, isSet = 0; + const byte* rawCert; + const byte* input; + byte* oidBuf; + word32 oid, idx = 0, tmpIdx = 0; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_INTEGER* a; + WOLFSSL_STACK* sk; + DecodedCert cert; + + WOLFSSL_ENTER("wolfSSL_X509_set_ext"); + + if(x509 == NULL){ + WOLFSSL_MSG("\tNot passed a certificate"); + return NULL; + } + + if(loc <0 || (loc > wolfSSL_X509_get_ext_count(x509))){ + WOLFSSL_MSG("\tBad location argument"); + return NULL; + } + + ext = wolfSSL_X509_EXTENSION_new(); + if (ext == NULL) { + WOLFSSL_MSG("\tX509_EXTENSION_new() failed"); + return NULL; + } + + rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz); + if (rawCert == NULL) { + WOLFSSL_MSG("\tX509_get_der() failed"); + wolfSSL_X509_EXTENSION_free(ext); + return NULL; + } + + InitDecodedCert( &cert, rawCert, (word32)outSz, 0); + + if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) { + WOLFSSL_MSG("\tCertificate parsing failed"); + wolfSSL_X509_EXTENSION_free(ext); + return NULL; + } + + input = cert.extensions; + sz = cert.extensionsSz; + + if (input == NULL || sz == 0) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + while (idx < (word32)sz) { + oid = 0; + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + tmpIdx = idx; + ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + idx = tmpIdx; + + /* Continue while loop until extCount == loc or idx > sz */ + if (extCount != loc) { + idx += length; + extCount++; + continue; + } + /* extCount == loc. Now get the extension. */ + /* Check if extension has been set */ + isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid); + ext->obj = wolfSSL_OBJ_nid2obj(oid); + if (ext->obj == NULL) { + WOLFSSL_MSG("\tfail: Invalid OBJECT"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->obj->nid = oid; + + switch (oid) { + case BASIC_CA_OID: + if (!isSet) + break; + /* Set pathlength */ + a = wolfSSL_ASN1_INTEGER_new(); + if (a == NULL) { + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + a->length = x509->pathLength; + + /* Save ASN1_INTEGER in x509 extension */ + ext->obj->pathlen = a; + + ext->obj->ca = x509->isCa; + ext->crit = x509->basicConstCrit; + break; + + case AUTH_INFO_OID: + if (!isSet) + break; + + /* Create a stack to hold both the caIssuer and ocsp objects + in X509_EXTENSION structure */ + sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), + NULL, DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + WOLFSSL_MSG("Failed to malloc stack"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT))); + + /* Add CaIssuers object to stack */ + if (x509->authInfoCaIssuer != NULL && + x509->authInfoCaIssuerSz > 0) + { + WOLFSSL_ASN1_OBJECT* obj; + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Error creating ASN1 object"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + obj->obj = (byte*)x509->authInfoCaIssuer; + obj->objSz = x509->authInfoCaIssuerSz; + obj->grp = oidCertAuthInfoType; + obj->nid = AIA_CA_ISSUER_OID; + + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + } + + /* Add OCSP object to stack */ + if (x509->authInfo != NULL && + x509->authInfoSz > 0) + { + WOLFSSL_ASN1_OBJECT* obj; + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Error creating ASN1 object"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + obj->obj = x509->authInfo; + obj->objSz = x509->authInfoSz; + obj->grp = oidCertAuthInfoType; + obj->nid = AIA_OCSP_OID; + + ret = wolfSSL_sk_ASN1_OBJECT_push(sk, obj); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + } + ext->ext_sk = sk; + ext->crit = x509->authInfoCrit; + break; + + case AUTH_KEY_OID: + if (!isSet) + break; + + ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->authKeyId, + x509->authKeyIdSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->crit = x509->authKeyIdCrit; + break; + + case SUBJ_KEY_OID: + if (!isSet) + break; + + ret = wolfSSL_ASN1_STRING_set(&ext->value, x509->subjKeyId, + x509->subjKeyIdSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->crit = x509->subjKeyIdCrit; + break; + + case CERT_POLICY_OID: + if (!isSet) + break; + ext->crit = x509->certPolicyCrit; + break; + + case KEY_USAGE_OID: + if (!isSet) + break; + + ret = wolfSSL_ASN1_STRING_set(&ext->value, + (byte*)&(x509->keyUsage), sizeof(word16)); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->crit = x509->keyUsageCrit; + break; + + case EXT_KEY_USAGE_OID: + if (!isSet) + break; + ext->crit = x509->keyUsageCrit; + break; + + case CRL_DIST_OID: + if (!isSet) + break; + ext->crit = x509->CRLdistCrit; + break; + + default: + WOLFSSL_MSG("Unknown extension type found, parsing OID"); + /* If the extension type is not recognized/supported, + set the ASN1_OBJECT in the extension with the + parsed oid for access in later function calls */ + + /* Get OID from input */ + if (GetASNObjectId(input, &idx, &length, sz) != 0) { + WOLFSSL_MSG("Failed to Get ASN Object Id"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + oidBuf = (byte*)XMALLOC(length+1+MAX_LENGTH_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (oidBuf == NULL) { + WOLFSSL_MSG("Failed to malloc tmp buffer"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + oidBuf[0] = ASN_OBJECT_ID; + objSz++; + objSz += SetLength(length, oidBuf + 1); + objSz += length; + + /* Set object size and reallocate space in object buffer */ + ext->obj->objSz = objSz; + if(((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || + (((ext->obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) == 0) && + (ext->obj->obj == NULL))) { + ext->obj->obj =(byte*)XREALLOC((byte*)ext->obj->obj, + ext->obj->objSz, + NULL,DYNAMIC_TYPE_ASN1); + if (ext->obj->obj == NULL) { + wolfSSL_ASN1_OBJECT_free(ext->obj); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA; + } else { + ext->obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + /* Get OID from input and copy to ASN1_OBJECT buffer */ + XMEMCPY(oidBuf+2, input+idx, length); + XMEMCPY((byte*)ext->obj->obj, oidBuf, ext->obj->objSz); + XFREE(oidBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + oidBuf = NULL; + ext->obj->grp = oidCertExtType; + ext->crit = 0; + + /* Get extension data and copy as ASN1_STRING */ + tmpIdx = idx + length; + if ((tmpIdx >= (word32)sz) || (input[tmpIdx++] != ASN_OCTET_STRING)) { + WOLFSSL_MSG("Error decoding unknown extension data"); + wolfSSL_ASN1_OBJECT_free(ext->obj); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + + if (GetLength(input, &tmpIdx, &length, sz) <= 0) { + WOLFSSL_MSG("Error: Invalid Input Length."); + wolfSSL_ASN1_OBJECT_free(ext->obj); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + ext->value.data = (char*)XMALLOC(length, NULL, DYNAMIC_TYPE_ASN1); + if (ext->value.data == NULL) { + WOLFSSL_MSG("Failed to malloc ASN1_STRING data"); + wolfSSL_X509_EXTENSION_free(ext); + FreeDecodedCert(&cert); + return NULL; + } + XMEMCPY(ext->value.data,input+tmpIdx,length); + ext->value.length = length; + } /* switch(oid) */ + + break; /* Got the Extension. Now exit while loop. */ + + } /* while(idx < sz) */ + + /* Store the new extension in a stack inside x509 + * The extensions on the stack are free'd internally when FreeX509 is called + */ + if (x509->ext_sk == NULL) + x509->ext_sk = wolfSSL_sk_new_x509_ext(); + if (x509->ext_sk != NULL) + wolfSSL_sk_X509_EXTENSION_push(x509->ext_sk, ext); + + FreeDecodedCert(&cert); + return ext; +} + +/* Return 0 on success and 1 on failure. Copies ext data to bio, using indent + * to pad the output. flag is ignored. */ +int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, WOLFSSL_X509_EXTENSION *ext, + unsigned long flag, int indent) +{ + int rc = WOLFSSL_FAILURE; + char tmp[CTC_NAME_SIZE*2]; + + if ((out != NULL) && (ext != NULL)) { + + XSNPRINTF(tmp, CTC_NAME_SIZE*2, "%*s%s", indent, "", ext->value.strData); + if (wolfSSL_BIO_write(out, tmp, (int)XSTRLEN(tmp)) == (int)XSTRLEN(tmp)) { + rc = WOLFSSL_SUCCESS; + } + } + (void) flag; + + return rc; +} + + +/* Returns pointer to ASN1_OBJECT from a X509_EXTENSION object */ +WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object(WOLFSSL_X509_EXTENSION* ex) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_object"); + if(ex == NULL){ + return NULL; + } + WOLFSSL_LEAVE("wolfSSL_X509_EXTENSION_get_object", WOLFSSL_SUCCESS); + return ex->obj; +} + +/* Returns crit flag in X509_EXTENSION object */ +int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_critical"); + if (ex == NULL) + return BAD_FUNC_ARG; + return ex->crit; +} + +/* Returns pointer to ASN1_STRING in X509_EXTENSION object */ +WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ex) +{ + WOLFSSL_ENTER("wolfSSL_X509_EXTENSION_get_data"); + if (ex == NULL) + return NULL; + return &ex->value; +} + +/* Creates v3_ext_method for a given X509v3 extension + * + * ex : The X509_EXTENSION used to create v3_ext_method. If the extension is + * not NULL, get the NID of the extension object and populate the + * extension type-specific X509V3_EXT_* function(s) in v3_ext_method. + * + * Returns NULL on error or pointer to the v3_ext_method populated with extension + * type-specific X509V3_EXT_* function(s). + * + * NOTE: NID_subject_key_identifier is currently the only extension implementing + * the X509V3_EXT_* functions, as it is the only type called directly by QT. The + * other extension types return a pointer to a v3_ext_method struct that contains + * only the NID. + */ +const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get(WOLFSSL_X509_EXTENSION* ex) +{ + int nid; + WOLFSSL_v3_ext_method method; + + WOLFSSL_ENTER("wolfSSL_X509V3_EXT_get"); + if ((ex == NULL) || (ex->obj == NULL)) { + WOLFSSL_MSG("Passed an invalid X509_EXTENSION*"); + return NULL; + } + /* Initialize all methods to NULL */ + method.d2i = NULL; + method.i2v = NULL; + method.i2s = NULL; + method.i2r = NULL; + + nid = ex->obj->nid; + if (nid <= 0) { + WOLFSSL_MSG("Failed to get nid from passed extension object"); + return NULL; + } + + switch (nid) { + case NID_basic_constraints: + break; + case NID_subject_key_identifier: + method.i2s = (X509V3_EXT_I2S)wolfSSL_i2s_ASN1_STRING; + break; + case NID_key_usage: + WOLFSSL_MSG("i2v function not yet implemented for Key Usage"); + break; + case NID_authority_key_identifier: + WOLFSSL_MSG("i2v function not yet implemented for Auth Key Id"); + break; + case NID_info_access: + WOLFSSL_MSG("i2v function not yet implemented for Info Access"); + break; + case NID_ext_key_usage: + WOLFSSL_MSG("i2v function not yet implemented for Ext Key Usage"); + break; + case NID_certificate_policies: + WOLFSSL_MSG("r2i function not yet implemented for Cert Policies"); + break; + case NID_crl_distribution_points: + WOLFSSL_MSG("r2i function not yet implemented for CRL Dist Points"); + break; + default: + /* If extension type is unknown, return NULL -- QT makes call to + X509_EXTENSION_get_data() if there is no v3_ext_method */ + WOLFSSL_MSG("X509V3_EXT_get(): Unknown extension type found"); + return NULL; + } + + method.ext_nid = nid; + ex->ext_method = method; + + return (const WOLFSSL_v3_ext_method*)&ex->ext_method; +} + +/* Parses and returns an x509v3 extension internal structure. + * + * ext : The X509_EXTENSION for parsing internal structure. If extension is + * not NULL, get the NID of the extension object and create a new + * extension-specific internal structure based on the extension type. + * + * Returns NULL on error or if NID is not found, otherwise returns a pointer to + * the extension type-specific X509_EXTENSION internal structure. + * Return is expected to be free'd by caller. + */ +void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ext) +{ + const WOLFSSL_v3_ext_method* method; + int ret, i; + WOLFSSL_ASN1_OBJECT* object; + WOLFSSL_ASN1_OBJECT* aiaEntry; + WOLFSSL_BASIC_CONSTRAINTS* bc; + WOLFSSL_AUTHORITY_KEYID* akey; + WOLFSSL_ASN1_STRING* asn1String, *newString; + WOLFSSL_AUTHORITY_INFO_ACCESS* aia; + WOLFSSL_STACK* sk; + + WOLFSSL_ENTER("wolfSSL_X509V3_EXT_d2i"); + + if(ext == NULL) { + WOLFSSL_MSG("Bad function Argument"); + return NULL; + } + + /* extract extension info */ + method = wolfSSL_X509V3_EXT_get(ext); + if (method == NULL) { + WOLFSSL_MSG("wolfSSL_X509V3_EXT_get error"); + return NULL; + } + object = wolfSSL_X509_EXTENSION_get_object(ext); + if (object == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_object failed"); + return NULL; + } + + /* Return pointer to proper internal structure based on NID */ + switch (object->type) { + /* basicConstraints */ + case (NID_basic_constraints): + WOLFSSL_MSG("basicConstraints"); + /* Allocate new BASIC_CONSTRAINTS structure */ + bc = (WOLFSSL_BASIC_CONSTRAINTS*) + XMALLOC(sizeof(WOLFSSL_BASIC_CONSTRAINTS), NULL, + DYNAMIC_TYPE_X509_EXT); + if (bc == NULL) { + WOLFSSL_MSG("Failed to malloc basic constraints"); + return NULL; + } + /* Copy pathlen and CA into BASIC_CONSTRAINTS from object */ + bc->ca = object->ca; + if (object->pathlen->length > 0) { + bc->pathlen = wolfSSL_ASN1_INTEGER_dup(object->pathlen); + if (bc->pathlen == NULL) { + WOLFSSL_MSG("Failed to duplicate ASN1_INTEGER"); + XFREE(bc, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + } + else + bc->pathlen = NULL; + return bc; + + /* subjectKeyIdentifier */ + case (NID_subject_key_identifier): + WOLFSSL_MSG("subjectKeyIdentifier"); + asn1String = wolfSSL_X509_EXTENSION_get_data(ext); + if (asn1String == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_data() failed"); + return NULL; + } + newString = wolfSSL_ASN1_STRING_new(); + if (newString == NULL) { + WOLFSSL_MSG("Failed to malloc ASN1_STRING"); + return NULL; + } + ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data, + asn1String->length); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_ASN1_STRING_free(newString); + return NULL; + }; + newString->type = asn1String->type; + return newString; + + /* authorityKeyIdentifier */ + case (NID_authority_key_identifier): + WOLFSSL_MSG("AuthorityKeyIdentifier"); + + akey = (WOLFSSL_AUTHORITY_KEYID*) + XMALLOC(sizeof(WOLFSSL_AUTHORITY_KEYID), NULL, + DYNAMIC_TYPE_X509_EXT); + if (akey == NULL) { + WOLFSSL_MSG("Failed to malloc authority key id"); + return NULL; + } + + akey->keyid = wolfSSL_ASN1_STRING_new(); + if (akey->keyid == NULL) { + WOLFSSL_MSG("ASN1_STRING_new() failed"); + wolfSSL_AUTHORITY_KEYID_free(akey); + return NULL; + } + + asn1String = wolfSSL_X509_EXTENSION_get_data(ext); + if (asn1String == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_data() failed"); + wolfSSL_AUTHORITY_KEYID_free(akey); + return NULL; + } + + ret = wolfSSL_ASN1_STRING_set(akey->keyid, asn1String->data, + asn1String->length); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_AUTHORITY_KEYID_free(akey); + return NULL; + }; + akey->keyid->type = asn1String->type; + + /* For now, set issuer and serial to NULL. This may need to be + updated for future use */ + akey->issuer = NULL; + akey->serial = NULL; + return akey; + + /* keyUsage */ + case (NID_key_usage): + WOLFSSL_MSG("keyUsage"); + /* This may need to be updated for future use. The i2v method for + keyUsage is not currently set. For now, return the ASN1_STRING + representation of KeyUsage bit string */ + asn1String = wolfSSL_X509_EXTENSION_get_data(ext); + if (asn1String == NULL) { + WOLFSSL_MSG("X509_EXTENSION_get_data() failed"); + return NULL; + } + newString = wolfSSL_ASN1_STRING_new(); + if (newString == NULL) { + WOLFSSL_MSG("Failed to malloc ASN1_STRING"); + return NULL; + } + ret = wolfSSL_ASN1_STRING_set(newString, asn1String->data, + asn1String->length); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_ASN1_STRING_free(newString); + return NULL; + }; + newString->type = asn1String->type; + return newString; + + /* extKeyUsage */ + case (NID_ext_key_usage): + WOLFSSL_MSG("extKeyUsage not supported yet"); + return NULL; + + /* certificatePolicies */ + case (NID_certificate_policies): + WOLFSSL_MSG("certificatePolicies not supported yet"); + return NULL; + + /* cRLDistributionPoints */ + case (NID_crl_distribution_points): + WOLFSSL_MSG("cRLDistributionPoints not supported yet"); + return NULL; + + /* authorityInfoAccess */ + case (NID_info_access): + WOLFSSL_MSG("AuthorityInfoAccess"); + /* i indexes into stack,sk,using wolfSSL_sk_value(sk,i) */ + i = 0; + + sk = ext->ext_sk; + if (sk == NULL) { + WOLFSSL_MSG("ACCESS_DESCRIPTION stack NULL"); + return NULL; + } + + /* AUTHORITY_INFO_ACCESS is a stack of ACCESS_DESCRIPTION entries */ + aia = wolfSSL_sk_new_null(); + if (aia == NULL) { + WOLFSSL_MSG("Failed to malloc AUTHORITY_INFO_ACCESS"); + return NULL; + } + aia->type = STACK_TYPE_ACCESS_DESCRIPTION; + + aiaEntry = wolfSSL_sk_value(sk,i); + /* ACCESS_DESCRIPTION has two members, method and location. + Method: ASN1_OBJECT as either AIA_OCSP_OID or AIA_CA_ISSUER_OID + Location: GENERAL_NAME structure containing the URI. */ + while (aiaEntry != NULL) { + WOLFSSL_ACCESS_DESCRIPTION* ad; + ad = (WOLFSSL_ACCESS_DESCRIPTION*) + XMALLOC(sizeof(WOLFSSL_ACCESS_DESCRIPTION), NULL, + DYNAMIC_TYPE_X509_EXT); + if (ad == NULL) { + WOLFSSL_MSG("Failed to malloc ACCESS_DESCRIPTION"); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + XMEMSET(ad, 0, sizeof(WOLFSSL_ACCESS_DESCRIPTION)); + + /* Create new ASN1_OBJECT from oid */ + ad->method = wolfSSL_OBJ_nid2obj(aiaEntry->nid); + if (ad->method == NULL) { + WOLFSSL_MSG("OBJ_nid2obj() failed"); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + + /* Allocate memory for GENERAL NAME */ + ad->location = (WOLFSSL_GENERAL_NAME*) + XMALLOC(sizeof(WOLFSSL_GENERAL_NAME), NULL, + DYNAMIC_TYPE_OPENSSL); + if (ad->location == NULL) { + WOLFSSL_MSG("Failed to malloc GENERAL_NAME"); + wolfSSL_ASN1_OBJECT_free(ad->method); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + XMEMSET(ad->location, 0, sizeof(WOLFSSL_GENERAL_NAME)); + ad->location->type = GEN_URI; + ad->location->d.uniformResourceIdentifier = + wolfSSL_ASN1_STRING_new(); + /* Set the URI in GENERAL_NAME */ + ret = wolfSSL_ASN1_STRING_set( + ad->location->d.uniformResourceIdentifier, + aiaEntry->obj, aiaEntry->objSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set() failed"); + wolfSSL_ASN1_OBJECT_free(ad->method); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + /* Push to AUTHORITY_INFO_ACCESS stack */ + ret = wolfSSL_sk_ACCESS_DESCRIPTION_push(aia, ad); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL); + wolfSSL_ASN1_OBJECT_free(ad->method); + XFREE(aia, NULL, DYNAMIC_TYPE_X509_EXT); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); + return NULL; + } + i++; + aiaEntry = wolfSSL_sk_value(sk,i); + } + return aia; + + default: + WOLFSSL_MSG("Extension NID not in table, returning NULL"); + break; + } + return NULL; +} + +/* Looks for the extension matching the passed in nid + * + * x509 : certificate to get parse through for extension. + * nid : Extension OID to be found. + * lastPos : Start search from extension after lastPos. + * Set to -1 to search from index 0. + * return >= 0 If successful the extension index is returned. + * return -1 If extension is not found or error is encountered. + */ +int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, int nid, int lastPos) +{ + int extCount = 0, length = 0, outSz = 0, sz = 0, ret = 0; + int isSet = 0, found = 0, loc; + const byte* rawCert; + const byte* input; + word32 oid, idx = 0, tmpIdx = 0; + DecodedCert cert; + + WOLFSSL_ENTER("wolfSSL_X509_get_ext_by_NID"); + + if(x509 == NULL){ + WOLFSSL_MSG("\tNot passed a certificate"); + return WOLFSSL_FATAL_ERROR; + } + + if(lastPos < -1 || (lastPos > (wolfSSL_X509_get_ext_count(x509) - 1))){ + WOLFSSL_MSG("\tBad location argument"); + return WOLFSSL_FATAL_ERROR; + } + + loc = lastPos + 1; + + rawCert = wolfSSL_X509_get_der((WOLFSSL_X509*)x509, &outSz); + if (rawCert == NULL) { + WOLFSSL_MSG("\tX509_get_der() failed"); + return WOLFSSL_FATAL_ERROR; + } + + InitDecodedCert( &cert, rawCert, (word32)outSz, 0); + + if (ParseCert(&cert, CA_TYPE, NO_VERIFY, NULL) < 0) { + WOLFSSL_MSG("\tCertificate parsing failed"); + return WOLFSSL_FATAL_ERROR; + } + + input = cert.extensions; + sz = cert.extensionsSz; + + if (input == NULL || sz == 0) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + while (idx < (word32)sz) { + oid = 0; + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + + tmpIdx = idx; + ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + FreeDecodedCert(&cert); + return WOLFSSL_FATAL_ERROR; + } + idx = tmpIdx; + + if (extCount >= loc) { + /* extCount >= loc. Now check if extension has been set */ + isSet = wolfSSL_X509_ext_isSet_by_NID((WOLFSSL_X509*)x509, oid); + + if (isSet && ((word32)nid == oid)) { + found = 1; + break; + } + } + + idx += length; + extCount++; + } /* while(idx < sz) */ + + FreeDecodedCert(&cert); + + return found ? extCount : WOLFSSL_FATAL_ERROR; +} + + #endif /* OPENSSL_ALL */ /* Looks for the extension matching the passed in nid @@ -7321,12 +8340,10 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, *c = -1; /* default to not found */ } - sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( - sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1); + sk = wolfSSL_sk_new_asn1_obj(); if (sk == NULL) { return NULL; } - XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT))); switch (nid) { case BASIC_CA_OID: @@ -7352,6 +8369,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, case ALT_NAMES_OID: { DNS_entry* dns = NULL; + sk->type = STACK_TYPE_GEN_NAME; if (x509->subjAltNameSet && x509->altNames != NULL) { /* alt names are DNS_entry structs */ @@ -7384,8 +8402,8 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, dns = dns->next; /* last dns in list add at end of function */ if (dns != NULL) { - if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != - WOLFSSL_SUCCESS) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) + != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Error pushing ASN1 object onto stack"); wolfSSL_ASN1_OBJECT_free(obj); wolfSSL_sk_ASN1_OBJECT_free(sk); @@ -7675,7 +8693,6 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, return sk; } - /* this function makes the assumption that out buffer is big enough for digest*/ int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out, unsigned int* outSz, const WOLFSSL_EVP_MD* evp, @@ -16059,7 +17076,45 @@ void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) { #endif /* NO_CERTS && OPENSSL_EXTRA */ -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_ALL) || defined (WOLFSSL_QT) +/* return 1 on success 0 on fail */ +int wolfSSL_sk_ACCESS_DESCRIPTION_push(WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk, + WOLFSSL_ACCESS_DESCRIPTION* access) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_ACCESS_DESCRIPTION_push"); + + if (sk == NULL || access == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.access == NULL) { + sk->data.access = access; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.access = sk->data.access; + node->next = sk->next; + node->type = sk->type; + sk->next = node; + sk->data.access = access; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} /* Frees all nodes in ACCESS_DESCRIPTION stack * @@ -16217,6 +17272,34 @@ void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name) } } +void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES *gens) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_GENERAL_NAMES_free"); + + if (gens == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = gens->next; + while (gens->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + gens->num -= 1; + } + + /* free head of stack */ + if (gens->num == 1) { + wolfSSL_ASN1_OBJECT_free(gens->data.obj); + } + XFREE(gens, NULL, DYNAMIC_TYPE_ASN1); +} + #endif /* OPENSSL_EXTRA */ #ifndef NO_FILESYSTEM @@ -16448,13 +17531,17 @@ void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) if (obj == NULL) { return; } - if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) { WOLFSSL_MSG("Freeing ASN1 data"); 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) { WOLFSSL_MSG("Freeing ASN1 OBJECT"); XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); @@ -16480,15 +17567,29 @@ WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; return obj; } -#endif /* NO_ASN */ +/* Creates and returns a new WOLFSSL_CIPHER stack. */ +WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void) +{ + WOLFSSL_STACK* sk = NULL; + 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_OBJEXT)* sk, - WOLFSSL_ASN1_OBJECT* obj) +int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, + WOLFSSL_ASN1_OBJECT* obj) { WOLFSSL_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_push"); + if (sk == NULL || obj == NULL) { return WOLFSSL_FAILURE; } @@ -16510,10 +17611,11 @@ int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); /* push new obj onto head of stack */ - node->data.obj = sk->data.obj; + node->data.obj = sk->data.obj; node->next = sk->next; + node->type = sk->type; sk->next = node; - sk->data.obj = obj; + sk->data.obj = obj; sk->num += 1; return WOLFSSL_SUCCESS; @@ -16550,12 +17652,16 @@ WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( } -#ifndef NO_ASN -/* free structure for x509 stack */ +/* 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_STACK* node; + WOLFSSL_ENTER("wolfSSL_sk_ASN1_OBJECT_free"); + if (sk == NULL) { return; } @@ -16630,6 +17736,50 @@ int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in) WOLFSSL_STUB("ASN1_STRING_to_UTF8"); return -1; } + +/* 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++) { + XSNPRINTF(val, valSz - 1, "%02X:", str[i]); + XSTRNCAT(tmp, val, valSz); + } + XSNPRINTF(val, valSz - 1, "%02X", str[i]); + XSTRNCAT(tmp, val, valSz); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return tmp; +} + #endif /* NO_ASN */ void wolfSSL_set_connect_state(WOLFSSL* ssl) @@ -20461,6 +21611,38 @@ void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) } +/* 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* dup; + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_dup"); + if (!src) + return NULL; + + dup = wolfSSL_ASN1_INTEGER_new(); + dup->negative = src->negative; + dup->dataMax = src->dataMax; + dup->isDynamic = src->isDynamic; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + dup->length = src->length; +#endif + XSTRNCPY((char*)dup->intData,(const char*)src->intData,WOLFSSL_ASN1_INTEGER_MAX); + + if (dup->isDynamic && src->data && dup->dataMax) { + dup->data = (unsigned char*) + XMALLOC(src->dataMax,NULL,DYNAMIC_TYPE_OPENSSL); + if (dup->data == NULL) { + return NULL; + } + XMEMCPY(dup->data,src->data,dup->dataMax); + } + return dup; +} + + /* sets the value of WOLFSSL_ASN1_INTEGER a to the long value v. */ int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v) { @@ -21878,6 +23060,48 @@ WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) } #endif +/* Return number of bytes written to BIO on success. 0 on failure. */ +WOLFSSL_API 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; +} + #if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) #ifndef NO_WOLFSSL_STUB /*** TBD ***/ @@ -22906,6 +24130,7 @@ void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time) int wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) { + WOLFSSL_ENTER("wolfSSL_sk_num"); if (sk == NULL) return 0; return (int)sk->num; @@ -23016,6 +24241,58 @@ void wolfSSL_sk_pop_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* 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; +} + +/* frees the wolfSSL_BASIC_CONSTRAINTS object */ +void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc) +{ + WOLFSSL_ENTER("wolfSSL_BASIC_CONSTRAINTS_free"); + if (bc == NULL) { + WOLFSSL_MSG("Argument is NULL"); + return; + } + if(bc->pathlen) { + wolfSSL_ASN1_INTEGER_free(bc->pathlen); + } + XFREE(bc, NULL, DYNAMIC_TYPE_OPENSSL); +} + +/* frees the wolfSSL_AUTHORITY_KEYID object */ +void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id) +{ + WOLFSSL_ENTER("wolfSSL_AUTHORITY_KEYID_free"); + if(id == NULL) { + WOLFSSL_MSG("Argument is NULL"); + return; + } + if (id->keyid) { + wolfSSL_ASN1_STRING_free(id->keyid); + } + if (id->issuer) { + wolfSSL_ASN1_OBJECT_free(id->issuer); + } + if (id->serial) { + wolfSSL_ASN1_INTEGER_free(id->serial); + } + XFREE(id, NULL, DYNAMIC_TYPE_OPENSSL); +} #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) @@ -36892,6 +38169,41 @@ err_exit: return WOLFSSL_FAILURE; } +#if (defined(WOLFSSL_QT) || defined(OPENSSL_ALL)) && !defined(NO_ASN) +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 /* (WOLFSSL_QT || OPENSSL_ALL) && !NO_ASN */ + #ifndef NO_ASN_TIME int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t) { diff --git a/tests/api.c b/tests/api.c index 82c86a803..59ba20da8 100644 --- a/tests/api.c +++ b/tests/api.c @@ -4623,6 +4623,14 @@ static void test_wolfSSL_PKCS5(void) (int)XSTRLEN((const char *) salt), 10, WC_SHA_DIGEST_SIZE,out); AssertIntEQ(ret, SSL_SUCCESS); + +#ifdef WOLFSSL_SHA512 + ret = PKCS5_PBKDF2_HMAC(passwd,(int)XSTRLEN(passwd), salt, + (int)XSTRLEN((const char *) salt), 10, + wolfSSL_EVP_sha512(), WC_SHA_DIGEST_SIZE, out); + AssertIntEQ(ret, SSL_SUCCESS); +#endif + XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_SHA) */ } @@ -21571,6 +21579,25 @@ static void test_wolfSSL_OBJ(void) #endif } +static void test_wolfSSL_i2a_ASN1_OBJECT(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_ASN) + 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); +#endif +} + static void test_wolfSSL_X509_NAME_ENTRY(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) \ @@ -23409,8 +23436,225 @@ static void test_wolfSSL_AES_cbc_encrypt() #endif } +static void test_wolfSSL_X509V3_EXT_get(void) { +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + FILE* f; + int numOfExt =0; + int extNid = 0; + int i = 0; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + const WOLFSSL_v3_ext_method* method; -static void test_wolfSSL_X509_get_ext_count(void) { + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + printf(testingFmt, "wolfSSL_X509V3_EXT_get() return struct and nid test"); + AssertIntEQ((numOfExt = wolfSSL_X509_get_ext_count(x509)), 3); + for (i = 0; i < numOfExt; i++) { + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(extNid = ext->obj->nid); + AssertNotNull(method = wolfSSL_X509V3_EXT_get(ext)); + AssertIntEQ(method->ext_nid, extNid); + } + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509V3_EXT_get() NULL argument test"); + AssertNull(method = wolfSSL_X509V3_EXT_get(NULL)); + printf(resultFmt, "passed"); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509V3_EXT_d2i(void) { +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + FILE* f; + int numOfExt = 0, nid = 0, i = 0, expected, actual; + char* str; + unsigned char* data; + const WOLFSSL_v3_ext_method* method; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_OBJECT *obj, *adObj; + WOLFSSL_ASN1_STRING* asn1str; + WOLFSSL_AUTHORITY_KEYID* aKeyId; + WOLFSSL_AUTHORITY_INFO_ACCESS* aia; + WOLFSSL_BASIC_CONSTRAINTS* bc; + WOLFSSL_ACCESS_DESCRIPTION* ad; + WOLFSSL_GENERAL_NAME* gn; + + printf(testingFmt, "wolfSSL_X509V3_EXT_d2i()"); + + /* Check NULL argument */ + AssertNull(wolfSSL_X509V3_EXT_d2i(NULL)); + + /* Using OCSP cert with X509V3 extensions */ + AssertNotNull(f = fopen("./certs/ocsp/root-ca-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + AssertIntEQ((numOfExt = wolfSSL_X509_get_ext_count(x509)), 5); + + /* Basic Constraints */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_basic_constraints); + AssertNotNull(bc = wolfSSL_X509V3_EXT_d2i(ext)); + + AssertIntEQ(bc->ca, 1); + AssertNull(bc->pathlen); + wolfSSL_BASIC_CONSTRAINTS_free(bc); + i++; + + /* Subject Key Identifier */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_subject_key_identifier); + + AssertNotNull(asn1str = wolfSSL_X509V3_EXT_d2i(ext)); + AssertNotNull(method = wolfSSL_X509V3_EXT_get(ext)); + AssertNotNull(method->i2s); + AssertNotNull(str = method->i2s((WOLFSSL_v3_ext_method*)method, asn1str)); + wolfSSL_ASN1_STRING_free(asn1str); + actual = strcmp(str, + "73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21"); + AssertIntEQ(actual, 0); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + i++; + + /* Authority Key Identifier */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_authority_key_identifier); + + AssertNotNull(aKeyId = wolfSSL_X509V3_EXT_d2i(ext)); + AssertNotNull(method = wolfSSL_X509V3_EXT_get(ext)); + AssertNotNull(asn1str = aKeyId->keyid); + AssertNotNull(str = + wolfSSL_i2s_ASN1_STRING((WOLFSSL_v3_ext_method*)method, asn1str)); + actual = strcmp(str, + "73:B0:1C:A4:2F:82:CB:CF:47:A5:38:D7:B0:04:82:3A:7E:72:15:21"); + AssertIntEQ(actual, 0); + XFREE(str, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_AUTHORITY_KEYID_free(aKeyId); + i++; + + /* Key Usage */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_key_usage); + + AssertNotNull(asn1str = wolfSSL_X509V3_EXT_d2i(ext)); + AssertNotNull(data = wolfSSL_ASN1_STRING_data(asn1str)); + expected = KEYUSE_KEY_CERT_SIGN | KEYUSE_CRL_SIGN; + actual = data[0]; + AssertIntEQ(actual, expected); + wolfSSL_ASN1_STRING_free(asn1str); +#if 0 + i++; + + /* Authority Info Access */ + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, i)); + AssertNotNull(obj = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ((nid = wolfSSL_OBJ_obj2nid(obj)), NID_info_access); + AssertNotNull(aia = wolfSSL_X509V3_EXT_d2i(ext)); + AssertIntEQ(wolfSSL_sk_num(aia), 1); /* Only one URI entry for this cert */ + + /* URI entry is an ACCESS_DESCRIPTION type */ + AssertNotNull(ad = wolfSSL_sk_value(aia, 0)); + AssertNotNull(adObj = ad->method); + /* Make sure nid is OCSP */ + AssertIntEQ(wolfSSL_OBJ_obj2nid(adObj), AIA_OCSP_OID); + + /* GENERAL_NAME stores URI as an ASN1_STRING */ + AssertNotNull(gn = ad->location); + AssertIntEQ(gn->type, GEN_URI); /* Type should always be GEN_URI */ + AssertNotNull(asn1str = gn->d.uniformResourceIdentifier); + AssertIntEQ(wolfSSL_ASN1_STRING_length(asn1str), 22); + str = (char*)wolfSSL_ASN1_STRING_data(asn1str); + actual = strcmp(str, "http://127.0.0.1:22220"); + AssertIntEQ(actual, 0); + + wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(aia, NULL); + XFREE(ad, NULL, DYNAMIC_TYPE_X509_EXT); +#else + (void) aia; (void) ad; (void) adObj; (void) gn; +#endif + wolfSSL_X509_free(x509); + printf(resultFmt, "passed"); +#endif +} + +static void test_wolfSSL_X509_get_ext(void){ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + int ret = 0; + FILE* f; + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* foundExtension; + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + AssertIntEQ((ret = wolfSSL_X509_get_ext_count(x509)), 3); + + printf(testingFmt, "wolfSSL_X509_get_ext() valid input"); + AssertNotNull(foundExtension = wolfSSL_X509_get_ext(x509, 0)); + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509_get_ext() valid x509, idx out of bounds"); + AssertNull(foundExtension = wolfSSL_X509_get_ext(x509, -1)); + AssertNull(foundExtension = wolfSSL_X509_get_ext(x509, 100)); + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509_get_ext() NULL x509, idx out of bounds"); + AssertNull(foundExtension = wolfSSL_X509_get_ext(NULL, -1)); + AssertNull(foundExtension = wolfSSL_X509_get_ext(NULL, 100)); + printf(resultFmt, "passed"); + + printf(testingFmt, "wolfSSL_X509_get_ext() NULL x509, valid idx"); + AssertNull(foundExtension = wolfSSL_X509_get_ext(NULL, 0)); + printf(resultFmt, "passed"); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_get_ext_by_NID(void) +{ +#if defined(OPENSSL_ALL) + int rc; + FILE* f; + WOLFSSL_X509* x509; + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, -1); + AssertIntGE(rc, 0); + + /* Start search from last location (should fail) */ + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, rc); + AssertIntGE(rc, -1); + + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, -2); + AssertIntGE(rc, -1); + + rc = wolfSSL_X509_get_ext_by_NID(NULL, NID_basic_constraints, -1); + AssertIntEQ(rc, -1); + + rc = wolfSSL_X509_get_ext_by_NID(x509, NID_undef, -1); + AssertIntEQ(rc, -1); + + wolfSSL_X509_free(x509); + +#endif +} + +static void test_wolfSSL_X509_get_ext_count(void) +{ #if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) FILE* f; WOLFSSL_X509* x509; @@ -23432,7 +23676,120 @@ static void test_wolfSSL_X509_get_ext_count(void) { #endif } -static void test_wolfSSL_X509_cmp(void){ +static void test_wolfSSL_X509_EXTENSION_new(void) +{ +#if defined (OPENSSL_ALL) + WOLFSSL_X509_EXTENSION* ext; + + AssertNotNull(ext = wolfSSL_X509_EXTENSION_new()); + AssertNotNull(ext->obj = wolfSSL_ASN1_OBJECT_new()); + ext->obj->nid = WOLFSSL_SUCCESS; + AssertIntEQ(WOLFSSL_SUCCESS, ext->obj->nid); + + wolfSSL_X509_EXTENSION_free(ext); +#endif +} + +static void test_wolfSSL_X509_EXTENSION_get_object(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_OBJECT* o; + FILE* file; + int nid = 0; + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_object() testing ext idx 0"); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, 0)); + AssertNotNull(o = wolfSSL_X509_EXTENSION_get_object(ext)); + AssertIntEQ(o->nid, 128); + nid = o->nid; + printf(resultFmt, nid == 128 ? passed : failed); + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_object() NULL argument"); + AssertNull(o = wolfSSL_X509_EXTENSION_get_object(NULL)); + printf(resultFmt, passed); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_EXTENSION_get_data(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + WOLFSSL_ASN1_STRING* str; + FILE* file; + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_data"); + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, 0)); + + AssertNotNull(str = wolfSSL_X509_EXTENSION_get_data(ext)); + printf(resultFmt, passed); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_EXTENSION_get_critical(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_EXTENSION* ext; + FILE* file; + int crit = -1; + + printf(testingFmt, "wolfSSL_X509_EXTENSION_get_critical"); + + AssertNotNull(file = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(file, NULL, NULL, NULL)); + fclose(file); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, 0)); + + crit = wolfSSL_X509_EXTENSION_get_critical(ext); + AssertIntEQ(crit, 0); + printf(resultFmt, passed); + + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509V3_EXT_print(void) +{ +#if !defined(NO_FILESYSTEM) && defined (OPENSSL_ALL) + FILE* f; + WOLFSSL_X509* x509; + X509_EXTENSION * ext = NULL; + int loc; + BIO *bio = NULL; + + AssertNotNull(f = fopen("./certs/server-cert.pem", "rb")); + AssertNotNull(x509 = wolfSSL_PEM_read_X509(f, NULL, NULL, NULL)); + fclose(f); + + loc = wolfSSL_X509_get_ext_by_NID(x509, NID_basic_constraints, -1); + AssertIntGT(loc, -1); + AssertNotNull(ext = wolfSSL_X509_get_ext(x509, loc)); + AssertNotNull(bio = wolfSSL_BIO_new(BIO_s_mem())); + + AssertIntEQ(wolfSSL_X509V3_EXT_print(bio, ext, 0, 0), WOLFSSL_SUCCESS); + + wolfSSL_BIO_free(bio); + wolfSSL_X509_free(x509); +#endif +} + +static void test_wolfSSL_X509_cmp(void) +{ #if defined(OPENSSL_ALL) FILE* file1; FILE* file2; @@ -25509,6 +25866,63 @@ static void test_wolfSSL_X509_print() #endif } +static void test_wolfSSL_ASN1_STRING_print(void){ +#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','!'}; + const unsigned int MAX_UNPRINTABLE_CHAR = 32; + const unsigned int MAX_BUF = 255; + const int LF = 10, CR = 13; + 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; + + printf(testingFmt, "wolfSSL_ASN1_STRING_print()"); + + /* 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 == LF || i == CR) + 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, + 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); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA && !NO_ASN && !NO_CERTS */ +} + static void test_wolfSSL_RSA_verify() { #if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && \ @@ -25801,6 +26215,7 @@ void ApiTest(void) test_wolfSSL_ERR_put_error(); test_wolfSSL_HMAC(); test_wolfSSL_OBJ(); + test_wolfSSL_i2a_ASN1_OBJECT(); test_wolfSSL_X509_NAME_ENTRY(); test_wolfSSL_BIO_gets(); test_wolfSSL_d2i_PUBKEY(); @@ -25844,8 +26259,18 @@ void ApiTest(void) test_wolfSSL_X509_print(); test_wolfSSL_RSA_verify(); + test_wolfSSL_X509V3_EXT_get(); + test_wolfSSL_X509V3_EXT_d2i(); + test_wolfSSL_X509_get_ext(); + test_wolfSSL_X509_get_ext_by_NID(); test_wolfSSL_X509_get_ext_count(); + test_wolfSSL_X509_EXTENSION_new(); + test_wolfSSL_X509_EXTENSION_get_object(); + test_wolfSSL_X509_EXTENSION_get_data(); + test_wolfSSL_X509_EXTENSION_get_critical(); + test_wolfSSL_X509V3_EXT_print(); test_wolfSSL_X509_cmp(); + test_wolfSSL_ASN1_STRING_print(); /* test the no op functions for compatibility */ test_no_op_functions(); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 277fae844..d41d2f7c3 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1622,3 +1622,29 @@ WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, return WOLFSSL_FAILURE; } #endif /* OPENSSL_EXTRA && !NO_PWDBASED !NO_SHA*/ + +#if defined(OPENSSL_EXTRA) && !defined(NO_PWDBASED) +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + const WOLFSSL_EVP_MD *digest, + int keylen, unsigned char *out) +{ + const char *nostring = ""; + int ret = 0; + + if (pass == NULL) { + passlen = 0; + pass = nostring; + } else if (passlen == -1) { + passlen = (int)XSTRLEN(pass); + } + + ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, + iter, keylen, wolfSSL_EVP_MD_type(digest)); + if (ret == 0) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FAILURE; +} +#endif /* OPENSSL_EXTRA && !NO_PWDBASED */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a0dc42b57..b87058eea 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3442,20 +3442,22 @@ struct WOLFSSL_STACK { unsigned long num; /* number of nodes in stack * (safety measure for freeing and shortcut for count) */ union { - WOLFSSL_X509* x509; - WOLFSSL_X509_NAME* name; - WOLFSSL_BIO* bio; - WOLFSSL_ASN1_OBJECT* obj; - #if defined(OPENSSL_ALL) + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* name; + WOLFSSL_BIO* bio; + WOLFSSL_ASN1_OBJECT* obj; + WOLFSSL_CIPHER* cipher; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) WOLFSSL_ACCESS_DESCRIPTION* access; - #endif - char* string; + WOLFSSL_X509_EXTENSION* ext; + #endif + void* generic; + char* string; } data; WOLFSSL_STACK* next; byte type; /* Identifies type of stack. */ }; - struct WOLFSSL_X509_NAME { char *name; int dynamicName; @@ -3492,11 +3494,19 @@ struct WOLFSSL_X509 { byte hwType[EXTERNAL_SERIAL_SIZE]; int hwSerialNumSz; byte hwSerialNum[EXTERNAL_SERIAL_SIZE]; - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) - byte certPolicySet; - byte certPolicyCrit; - #endif /* OPENSSL_EXTRA */ -#endif +#endif /* WOLFSSL_SEP */ +#if (defined(WOLFSSL_SEP) || defined(WOLFSSL_QT) || defined (OPENSSL_ALL)) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + byte certPolicySet; + byte certPolicyCrit; +#endif /* (WOLFSSL_SEP || WOLFSSL_QT) && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + WOLFSSL_ASN1_TIME* notAfterTime; + WOLFSSL_ASN1_TIME* notBeforeTime; + WOLFSSL_STACK* ext_sk; /* Store X509_EXTENSIONS from wolfSSL_X509_get_ext */ + WOLFSSL_STACK* ext_d2i;/* Store d2i extensions from wolfSSL_X509_get_ext_d2i */ + WOLFSSL_ASN1_INTEGER* serialNumber; /* Stores SN from wolfSSL_X509_get_serialNumber */ +#endif /* WOLFSSL_QT || OPENSSL_ALL */ int notBeforeSz; int notAfterSz; byte notBefore[MAX_DATE_SZ]; @@ -3507,12 +3517,12 @@ struct WOLFSSL_X509 { buffer pubKey; int pubKeyOID; DNS_entry* altNamesNext; /* hint for retrieval */ - #if defined(HAVE_ECC) || defined(HAVE_ED25519) - word32 pkCurveOID; - #endif /* HAVE_ECC */ - #ifndef NO_CERTS - DerBuffer* derCert; /* may need */ - #endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + word32 pkCurveOID; +#endif /* HAVE_ECC */ +#ifndef NO_CERTS + DerBuffer* derCert; /* may need */ +#endif void* heap; /* heap hint */ byte dynamicMemory; /* dynamic memory flag */ byte isCa:1; @@ -3533,6 +3543,10 @@ struct WOLFSSL_X509 { byte* extKeyUsageSrc; const byte* CRLInfo; byte* authInfo; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + byte* authInfoCaIssuer; + int authInfoCaIssuerSz; +#endif word32 pathLength; word16 keyUsage; int CRLInfoSz; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 89dc981a5..3fdba0ac5 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -436,6 +436,11 @@ WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char * pass, int passlen, int saltlen, int iter, int keylen, unsigned char *out); +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + const WOLFSSL_EVP_MD *digest, + int keylen, unsigned char *out); #define EVP_CIPH_STREAM_CIPHER WOLFSSL_EVP_CIPH_STREAM_CIPHER #define EVP_CIPH_ECB_MODE WOLFSSL_EVP_CIPH_ECB_MODE #define EVP_CIPH_CBC_MODE WOLFSSL_EVP_CIPH_CBC_MODE @@ -611,6 +616,7 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define wolfSSL_OPENSSL_add_all_algorithms_noconf wolfSSL_OpenSSL_add_all_algorithms_noconf #define PKCS5_PBKDF2_HMAC_SHA1 wolfSSL_PKCS5_PBKDF2_HMAC_SHA1 +#define PKCS5_PBKDF2_HMAC wolfSSL_PKCS5_PBKDF2_HMAC #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 /* sha512 */ diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 10580376e..2a9edc098 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -88,6 +88,7 @@ typedef WOLFSSL_ASN1_STRING ASN1_STRING; typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; typedef WOLFSSL_BUF_MEM BUF_MEM; typedef WOLFSSL_GENERAL_NAME GENERAL_NAME; +typedef WOLFSSL_GENERAL_NAMES GENERAL_NAMES; #define ASN1_UTCTIME WOLFSSL_ASN1_TIME #define ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME @@ -261,9 +262,16 @@ typedef WOLFSSL_X509_VERIFY_PARAM X509_VERIFY_PARAM; #define SSL_SESSION_get_master_key wolfSSL_SESSION_get_master_key #define SSL_SESSION_get_master_key_length wolfSSL_SESSION_get_master_key_length -#if defined(OPENSSL_ALL) +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + #define ASN1_BOOLEAN WOLFSSL_ASN1_BOOLEAN + #define X509_get_ext wolfSSL_X509_get_ext #define X509_cmp wolfSSL_X509_cmp #define X509_get_ext_count wolfSSL_X509_get_ext_count + #define X509_EXTENSION_get_object wolfSSL_X509_EXTENSION_get_object + #define X509_EXTENSION_get_critical wolfSSL_X509_EXTENSION_get_critical + #define X509_EXTENSION_get_data wolfSSL_X509_EXTENSION_get_data + #define X509_EXTENSION_new wolfSSL_X509_EXTENSION_new + #define X509_EXTENSION_free wolfSSL_X509_EXTENSION_free #endif #define DSA_dup_DH wolfSSL_DSA_dup_DH @@ -292,6 +300,7 @@ typedef WOLFSSL_X509_VERIFY_PARAM X509_VERIFY_PARAM; #define X509_load_certificate_file wolfSSL_X509_load_certificate_file #define X509_digest wolfSSL_X509_digest #define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i +#define X509_get_ext_by_NID wolfSSL_X509_get_ext_by_NID #define X509_get_issuer_name wolfSSL_X509_get_issuer_name #define X509_get_subject_name wolfSSL_X509_get_subject_name #define X509_get_pubkey wolfSSL_X509_get_pubkey @@ -487,11 +496,14 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define ASN1_INTEGER_set wolfSSL_ASN1_INTEGER_set #define ASN1_INTEGER_to_BN wolfSSL_ASN1_INTEGER_to_BN +#define i2a_ASN1_OBJECT wolfSSL_i2a_ASN1_OBJECT + #define ASN1_STRING_data wolfSSL_ASN1_STRING_data #define ASN1_STRING_get0_data wolfSSL_ASN1_STRING_data #define ASN1_STRING_length wolfSSL_ASN1_STRING_length #define ASN1_STRING_to_UTF8 wolfSSL_ASN1_STRING_to_UTF8 #define ASN1_STRING_print_ex wolfSSL_ASN1_STRING_print_ex +#define ASN1_STRING_print(x, y) wolfSSL_ASN1_STRING_print ((WOLFSSL_BIO*)(x), (WOLFSSL_ASN1_STRING*)(y)) #define ASN1_UTCTIME_pr wolfSSL_ASN1_UTCTIME_pr @@ -504,7 +516,7 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_CTX_get_client_CA_list wolfSSL_SSL_CTX_get_client_CA_list #define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list #define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store -#define SSL_CTX_get_cert_store wolfSSL_CTX_get_cert_store +#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) #define SSL_get_ex_data_X509_STORE_CTX_idx wolfSSL_get_ex_data_X509_STORE_CTX_idx #define SSL_get_ex_data wolfSSL_get_ex_data @@ -701,7 +713,6 @@ enum { #if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) #include -typedef STACK_OF(WOLFSSL_ASN1_OBJECT) GENERAL_NAMES; #define SSL_CTRL_CHAIN 88 #define BIO_CTRL_WPENDING 13 #define GEN_IPADD 7 @@ -717,7 +728,6 @@ typedef STACK_OF(WOLFSSL_ASN1_OBJECT) GENERAL_NAMES; #define d2i_PrivateKey_bio wolfSSL_d2i_PrivateKey_bio #define BIO_new_bio_pair wolfSSL_BIO_new_bio_pair #define SSL_get_verify_callback wolfSSL_get_verify_callback -#define GENERAL_NAMES_free(GENERAL_NAMES)NULL #define SSL_set_mode(ssl,op) wolfSSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL) @@ -856,6 +866,7 @@ typedef STACK_OF(WOLFSSL_ASN1_OBJECT) GENERAL_NAMES; #define SSL_SESSION_get_id wolfSSL_SESSION_get_id #define sk_GENERAL_NAME_pop_free wolfSSL_sk_GENERAL_NAME_pop_free #define GENERAL_NAME_free wolfSSL_GENERAL_NAME_free +#define GENERAL_NAMES_free wolfSSL_GENERAL_NAMES_free #define SSL3_AL_FATAL 2 #define SSL_TLSEXT_ERR_OK 0 diff --git a/wolfssl/openssl/x509v3.h b/wolfssl/openssl/x509v3.h index 09dde0b5f..bb159a674 100644 --- a/wolfssl/openssl/x509v3.h +++ b/wolfssl/openssl/x509v3.h @@ -31,12 +31,67 @@ extern "C" { #endif +/* Forward reference */ +typedef struct WOLFSSL_v3_ext_method WOLFSSL_v3_ext_method; + +typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long); +typedef STACK_OF(CONF_VALUE) *(*X509V3_EXT_I2V) ( + struct WOLFSSL_v3_ext_method *method, + void *ext, STACK_OF(CONF_VALUE) *extlist); +typedef char *(*X509V3_EXT_I2S)(struct WOLFSSL_v3_ext_method *method, void *ext); +typedef int (*X509V3_EXT_I2R) (struct WOLFSSL_v3_ext_method *method, + void *ext, BIO *out, int indent); +typedef struct WOLFSSL_v3_ext_method X509V3_EXT_METHOD; + +struct WOLFSSL_v3_ext_method { + int ext_nid; + int ext_flags; + void *usr_data; + X509V3_EXT_D2I d2i; + X509V3_EXT_I2V i2v; + X509V3_EXT_I2S i2s; + X509V3_EXT_I2R i2r; +}; + +#define WOLFSSL_ASN1_BOOLEAN int + +struct WOLFSSL_X509_EXTENSION { + WOLFSSL_ASN1_OBJECT *obj; + WOLFSSL_ASN1_BOOLEAN crit; + WOLFSSL_ASN1_STRING value; + WOLFSSL_v3_ext_method ext_method; + WOLFSSL_STACK* ext_sk; /* For extension specific data */ +}; + struct WOLFSSL_ACCESS_DESCRIPTION { WOLFSSL_ASN1_OBJECT *method; WOLFSSL_GENERAL_NAME *location; }; +typedef struct WOLFSSL_AUTHORITY_KEYID AUTHORITY_KEYID; +typedef struct WOLFSSL_BASIC_CONSTRAINTS BASIC_CONSTRAINTS; typedef struct WOLFSSL_ACCESS_DESCRIPTION ACCESS_DESCRIPTION; +typedef WOLF_STACK_OF(WOLFSSL_ACCESS_DESCRIPTION) WOLFSSL_AUTHORITY_INFO_ACCESS; + +WOLFSSL_API void wolfSSL_BASIC_CONSTRAINTS_free(WOLFSSL_BASIC_CONSTRAINTS *bc); +WOLFSSL_API void wolfSSL_AUTHORITY_KEYID_free(WOLFSSL_AUTHORITY_KEYID *id); +WOLFSSL_API const WOLFSSL_v3_ext_method* wolfSSL_X509V3_EXT_get( + WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API void* wolfSSL_X509V3_EXT_d2i(WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API char* wolfSSL_i2s_ASN1_STRING(WOLFSSL_v3_ext_method *method, + const WOLFSSL_ASN1_STRING *s); +WOLFSSL_API int wolfSSL_X509V3_EXT_print(WOLFSSL_BIO *out, + WOLFSSL_X509_EXTENSION *ext, unsigned long flag, int indent); + +#define BASIC_CONSTRAINTS_free wolfSSL_BASIC_CONSTRAINTS_free +#define AUTHORITY_KEYID_free wolfSSL_AUTHORITY_KEYID_free +#define SSL_CTX_get_cert_store(x) wolfSSL_CTX_get_cert_store ((WOLFSSL_CTX*) (x)) +#define ASN1_INTEGER WOLFSSL_ASN1_INTEGER +#define ASN1_OCTET_STRING WOLFSSL_ASN1_STRING +#define X509V3_EXT_get wolfSSL_X509V3_EXT_get +#define X509V3_EXT_d2i wolfSSL_X509V3_EXT_d2i +#define i2s_ASN1_OCTET_STRING wolfSSL_i2s_ASN1_STRING +#define X509V3_EXT_print wolfSSL_X509V3_EXT_print #ifdef __cplusplus } diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index a51652761..0f4765d33 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -180,6 +180,8 @@ typedef struct WOLFSSL_DH WOLFSSL_DH; typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; typedef struct WOLFSSL_GENERAL_NAME WOLFSSL_GENERAL_NAME; +typedef struct WOLFSSL_AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID; +typedef struct WOLFSSL_BASIC_CONSTRAINTS WOLFSSL_BASIC_CONSTRAINTS; typedef struct WOLFSSL_ACCESS_DESCRIPTION WOLFSSL_ACCESS_DESCRIPTION; #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) @@ -196,6 +198,17 @@ struct WOLFSSL_GENERAL_NAME { } d; }; +struct WOLFSSL_AUTHORITY_KEYID { + WOLFSSL_ASN1_STRING *keyid; + WOLFSSL_ASN1_OBJECT *issuer; + WOLFSSL_ASN1_INTEGER *serial; +}; + +struct WOLFSSL_BASIC_CONSTRAINTS { + int ca; + WOLFSSL_ASN1_INTEGER *pathlen; +}; + #endif /* OPENSSL_ALL || OPENSSL_EXTRA*/ #define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME @@ -212,6 +225,10 @@ struct WOLFSSL_ASN1_INTEGER { unsigned char* data; unsigned int dataMax; /* max size of data buffer */ unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + int length; +#endif }; struct WOLFSSL_ASN1_TIME { @@ -242,11 +259,20 @@ struct WOLFSSL_ASN1_OBJECT { unsigned char dynamic; /* if 1 then obj was dynamiclly created, 0 otherwise */ #define WOLFSSL_ASN1_DYNAMIC 0x1 #define WOLFSSL_ASN1_DYNAMIC_DATA 0x2 - struct d { /* dereferenced */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) + int ca; + WOLFSSL_ASN1_INTEGER *pathlen; +#endif + + struct d { /* derefrenced */ + WOLFSSL_ASN1_STRING* dNSName; WOLFSSL_ASN1_STRING ia5_internal; WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */ - WOLFSSL_ASN1_STRING* dNSName; - WOLFSSL_ASN1_STRING* iPAddress; +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) + WOLFSSL_ASN1_STRING* uniformResourceIdentifier; + WOLFSSL_ASN1_STRING iPAddress_internal; +#endif + WOLFSSL_ASN1_STRING* iPAddress; /* points to iPAddress_internal */ } d; }; @@ -821,10 +847,15 @@ WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long); #include "wolfssl/wolfcrypt/asn.h" #endif -#if defined(OPENSSL_ALL) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT) +WOLFSSL_API int wolfSSL_sk_ACCESS_DESCRIPTION_push( + WOLF_STACK_OF(ACCESS_DESCRIPTION)* sk, + WOLFSSL_ACCESS_DESCRIPTION* access); WOLFSSL_API void wolfSSL_sk_ACCESS_DESCRIPTION_pop_free(WOLFSSL_STACK* sk, void f (WOLFSSL_ACCESS_DESCRIPTION*)); -#endif /* defined(OPENSSL_ALL) */ +#endif /* defined(OPENSSL_ALL) || defined(WOLFSSL_QT) */ + +typedef WOLF_STACK_OF(WOLFSSL_GENERAL_NAME) WOLFSSL_GENERAL_NAMES; WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509); @@ -837,8 +868,10 @@ WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk); WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk, void f (WOLFSSL_GENERAL_NAME*)); WOLFSSL_API void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name); +WOLFSSL_API void wolfSSL_GENERAL_NAMES_free(WOLFSSL_GENERAL_NAMES* name); WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void); WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_asn1_obj(void); WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, WOLFSSL_ASN1_OBJECT* obj); WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( @@ -1080,6 +1113,8 @@ WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*); WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*); WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_dup( + const WOLFSSL_ASN1_INTEGER* src); WOLFSSL_API int wolfSSL_ASN1_INTEGER_set(WOLFSSL_ASN1_INTEGER *a, long v); WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*); @@ -2741,6 +2776,8 @@ WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, int* idx); +WOLFSSL_API int wolfSSL_X509_get_ext_by_NID(const WOLFSSL_X509* x509, + int nid, int lastPos); WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len); WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509); @@ -2755,9 +2792,20 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx, unsigned char* der, long derSz); -#if defined(OPENSSL_ALL) +#if defined(WOLFSSL_QT) || defined(OPENSSL_ALL) WOLFSSL_API int wolfSSL_X509_cmp(const WOLFSSL_X509* a, const WOLFSSL_X509* b); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509* x, int loc); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_set_ext(WOLFSSL_X509* x, int loc); WOLFSSL_API int wolfSSL_X509_get_ext_count(const WOLFSSL_X509* passed_cert); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object(WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API int wolfSSL_X509_EXTENSION_get_critical(const WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data(WOLFSSL_X509_EXTENSION* ex); +WOLFSSL_API WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_new(void); +WOLFSSL_API int wolfSSL_sk_X509_EXTENSION_push(WOLFSSL_STACK* sk, + WOLFSSL_X509_EXTENSION* ext); +WOLFSSL_API void wolfSSL_sk_X509_EXTENSION_free(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_X509_EXTENSION_free(WOLFSSL_X509_EXTENSION* ext_to_free); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_new_x509_ext(void); #endif #endif /* NO_CERTS */ @@ -3149,6 +3197,7 @@ WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const WOLFSSL_API void *X509_get_X509_PUBKEY(void * x); WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub); WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API int wolfSSL_i2a_ASN1_OBJECT(WOLFSSL_BIO *bp, WOLFSSL_ASN1_OBJECT *a); WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir); @@ -3161,6 +3210,7 @@ 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 WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 9e989cbc6..008ebe2da 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -168,6 +168,7 @@ enum NID_info_access = 69, NID_sinfo_access = 79, /* id-pe 11 */ NID_name_constraints = 144, /* 2.5.29.30 */ + NID_crl_distribution_points = 145, /* 2.5.29.31 */ NID_certificate_policies = 146, NID_policy_mappings = 147, NID_policy_constraints = 150,