diff --git a/src/ssl.c b/src/ssl.c index f0f568fe1..7357b5bce 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -51586,14 +51586,61 @@ int wolfSSL_X509_REQ_sign_ctx(WOLFSSL_X509 *req, return WOLFSSL_FAILURE; } -#ifndef NO_WOLFSSL_STUB int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, - WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext) + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext_sk) { - (void)req; - (void)ext; - return WOLFSSL_FAILURE; + if (!req || !ext_sk) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + while (ext_sk) { + WOLFSSL_X509_EXTENSION* ext = ext_sk->data.ext; + + switch (ext->obj->type) { + case NID_subject_alt_name: + { + WOLFSSL_GENERAL_NAMES* gns = ext->ext_sk; + while (gns) { + WOLFSSL_GENERAL_NAME* gn = gns->data.gn; + if (!gn || !gn->d.ia5 || + wolfSSL_X509_add_altname_ex(req, gn->d.ia5->data, + gn->d.ia5->length, gn->type) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Subject alternative name missing extension"); + return WOLFSSL_FAILURE; + } + gns = gns->next; + } + req->subjAltNameSet = 1; + req->subjAltNameCrit = ext->crit; + break; + } + case NID_key_usage: + if (ext && ext->value.data && + ext->value.length == sizeof(word16)) { + req->keyUsage = *(word16*)ext->value.data; + req->keyUsageCrit = ext->crit; + } + break; + case NID_basic_constraints: + if (ext->obj) { + req->isCa = ext->obj->ca; + req->basicConstCrit = ext->crit; + if (ext->obj->pathlen) + req->pathLength = ext->obj->pathlen->length; + } + break; + default: + WOLFSSL_MSG("Unsupported extension to add"); + return WOLFSSL_FAILURE; + } + + ext_sk = ext_sk->next; + } + + return WOLFSSL_SUCCESS; } +#ifndef NO_WOLFSSL_STUB int wolfSSL_X509_REQ_add1_attr_by_txt(WOLFSSL_X509 *req, const char *attrname, int type, const unsigned char *bytes, int len) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 7334ec123..dc44a3b8b 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8882,18 +8882,23 @@ static int DecodeCertExtensions(DecodedCert* cert) if (input == NULL || sz == 0) return BAD_FUNC_ARG; - if (GetASNTag(input, &idx, &tag, sz) < 0) { - return ASN_PARSE_E; - } +#ifdef WOLFSSL_CERT_REQ + if (!cert->isCSR) +#endif + { /* Not included in CSR */ + if (GetASNTag(input, &idx, &tag, sz) < 0) { + return ASN_PARSE_E; + } - if (tag != ASN_EXTENSIONS) { - WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); - return ASN_PARSE_E; - } + if (tag != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + return ASN_PARSE_E; + } - if (GetLength(input, &idx, &length, sz) < 0) { - WOLFSSL_MSG("\tfail: invalid length"); - return ASN_PARSE_E; + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + return ASN_PARSE_E; + } } if (GetSequence(input, &idx, &length, sz) < 0) { @@ -9626,27 +9631,33 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) WOLFSSL_MSG("attr GetSet error"); return ASN_PARSE_E; } - /* For now all supported attributes have the type value - * of ASN_PRINTABLE_STRING or ASN_UTF8STRING but as more - * attributes are supported then this will have to be done - * on a per attribute basis. */ - if (GetHeader(cert->source, &tag, - &cert->srcIdx, &len, attrMaxIdx, 1) < 0) { - WOLFSSL_MSG("attr GetHeader error"); - return ASN_PARSE_E; - } - if (tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING && - tag != ASN_IA5_STRING) { - WOLFSSL_MSG("Unsupported attribute value format"); - return ASN_PARSE_E; - } switch (oid) { case CHALLENGE_PASSWORD_OID: + if (GetHeader(cert->source, &tag, + &cert->srcIdx, &len, attrMaxIdx, 1) < 0) { + WOLFSSL_MSG("attr GetHeader error"); + return ASN_PARSE_E; + } + if (tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING && + tag != ASN_IA5_STRING) { + WOLFSSL_MSG("Unsupported attribute value format"); + return ASN_PARSE_E; + } cert->cPwd = (char*)cert->source + cert->srcIdx; cert->cPwdLen = len; cert->srcIdx += len; break; case SERIAL_NUMBER_OID: + if (GetHeader(cert->source, &tag, + &cert->srcIdx, &len, attrMaxIdx, 1) < 0) { + WOLFSSL_MSG("attr GetHeader error"); + return ASN_PARSE_E; + } + if (tag != ASN_PRINTABLE_STRING && tag != ASN_UTF8STRING && + tag != ASN_IA5_STRING) { + WOLFSSL_MSG("Unsupported attribute value format"); + return ASN_PARSE_E; + } cert->sNum = (char*)cert->source + cert->srcIdx; cert->sNumLen = len; cert->srcIdx += len; @@ -9655,6 +9666,20 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) cert->serialSz = cert->sNumLen; } break; + case EXTENSION_REQUEST_OID: + /* save extensions */ + cert->extensions = &cert->source[cert->srcIdx]; + cert->extensionsSz = len; + cert->extensionsIdx = cert->srcIdx; /* for potential later use */ + + if ((ret = DecodeCertExtensions(cert)) < 0) { + if (ret == ASN_CRIT_EXT_E) + cert->criticalExt = ret; + else + return ret; + } + cert->srcIdx += len; + break; default: WOLFSSL_MSG("Unsupported attribute type"); return ASN_PARSE_E; diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index cef18b570..be30dff38 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3596,7 +3596,7 @@ WOLFSSL_API int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, WOLFSSL_API int wolfSSL_X509_REQ_sign_ctx(WOLFSSL_X509 *req, WOLFSSL_EVP_MD_CTX* md_ctx); WOLFSSL_API int wolfSSL_X509_REQ_add_extensions(WOLFSSL_X509* req, - WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext); + WOLF_STACK_OF(WOLFSSL_X509_EXTENSION)* ext_sk); WOLFSSL_API int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, WOLFSSL_X509_NAME *name); WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f7132f64b..b6d1e836c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -599,9 +599,10 @@ enum KeyIdType { #endif #ifdef WOLFSSL_CERT_REQ -enum CsrAttyType { +enum CsrAttrType { CHALLENGE_PASSWORD_OID = 659, SERIAL_NUMBER_OID = 94, + EXTENSION_REQUEST_OID = 666, }; #endif