Skip to content

Commit ea7ea35

Browse files
committed
Fixes for WOLFSSL_X509 cert generation with key usage, extended key usage, and basic constraints
1 parent b8119af commit ea7ea35

5 files changed

Lines changed: 218 additions & 88 deletions

File tree

src/ssl_asn1.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,9 @@ WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_dup(WOLFSSL_ASN1_OBJECT* obj)
16061606
dupl->grp = obj->grp;
16071607
dupl->nid = obj->nid;
16081608
dupl->objSz = obj->objSz;
1609+
#ifdef OPENSSL_EXTRA
1610+
dupl->ca = obj->ca;
1611+
#endif
16091612
/* Check for encoding. */
16101613
if (obj->obj) {
16111614
/* Allocate memory for ASN.1 OBJECT_ID DER encoding. */

src/x509.c

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,11 +1360,45 @@ int wolfSSL_X509_add_ext(WOLFSSL_X509 *x509, WOLFSSL_X509_EXTENSION *ext, int lo
13601360
break;
13611361
}
13621362
case NID_key_usage:
1363-
if (ext && ext->value.data &&
1364-
ext->value.length == sizeof(word16)) {
1365-
x509->keyUsage = *(word16*)ext->value.data;
1366-
x509->keyUsageCrit = (byte)ext->crit;
1367-
x509->keyUsageSet = 1;
1363+
if (ext && ext->value.data) {
1364+
if (ext->value.length == sizeof(word16)) {
1365+
/* if ext->value is already word16, set directly */
1366+
x509->keyUsage = *(word16*)ext->value.data;
1367+
x509->keyUsageCrit = (byte)ext->crit;
1368+
x509->keyUsageSet = 1;
1369+
}
1370+
else if (ext->value.length > 0) {
1371+
/* ext->value is comma-delimited string, convert to word16 */
1372+
if (ParseKeyUsageStr(ext->value.data, &x509->keyUsage,
1373+
x509->heap) != 0) {
1374+
return WOLFSSL_FAILURE;
1375+
}
1376+
x509->keyUsageCrit = (byte)ext->crit;
1377+
x509->keyUsageSet = 1;
1378+
}
1379+
else {
1380+
return WOLFSSL_FAILURE;
1381+
}
1382+
}
1383+
break;
1384+
case NID_ext_key_usage:
1385+
if (ext && ext->value.data) {
1386+
if (ext->value.length == sizeof(byte)) {
1387+
/* if ext->value is already word16, set directly */
1388+
x509->extKeyUsage = *(byte*)ext->value.data;
1389+
x509->extKeyUsageCrit = (byte)ext->crit;
1390+
}
1391+
else if (ext->value.length > 0) {
1392+
/* ext->value is comma-delimited string, convert to word16 */
1393+
if (ParseExtKeyUsageStr(ext->value.data, &x509->extKeyUsage,
1394+
x509->heap) != 0) {
1395+
return WOLFSSL_FAILURE;
1396+
}
1397+
x509->extKeyUsageCrit = (byte)ext->crit;
1398+
}
1399+
else {
1400+
return WOLFSSL_FAILURE;
1401+
}
13681402
}
13691403
break;
13701404
case NID_basic_constraints:
@@ -2781,6 +2815,14 @@ static WOLFSSL_X509_EXTENSION* createExtFromStr(int nid, const char *value)
27812815
}
27822816
ext->value.type = KEY_USAGE_OID;
27832817
break;
2818+
case NID_ext_key_usage:
2819+
if (wolfSSL_ASN1_STRING_set(&ext->value, value, -1)
2820+
!= WOLFSSL_SUCCESS) {
2821+
WOLFSSL_MSG("wolfSSL_ASN1_STRING_set error");
2822+
goto err_cleanup;
2823+
}
2824+
ext->value.type = EXT_KEY_USAGE_OID;
2825+
break;
27842826
default:
27852827
WOLFSSL_MSG("invalid or unsupported NID");
27862828
goto err_cleanup;

tests/api.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46250,27 +46250,51 @@ static int test_wolfSSL_X509V3_EXT_nconf(void)
4625046250
"authorityKeyIdentifier",
4625146251
"subjectAltName",
4625246252
"keyUsage",
46253+
"extendedKeyUsage",
4625346254
};
4625446255
size_t ext_names_count = sizeof(ext_names)/sizeof(*ext_names);
4625546256
int ext_nids[] = {
4625646257
NID_subject_key_identifier,
4625746258
NID_authority_key_identifier,
4625846259
NID_subject_alt_name,
4625946260
NID_key_usage,
46261+
NID_ext_key_usage,
4626046262
};
4626146263
size_t ext_nids_count = sizeof(ext_nids)/sizeof(*ext_nids);
4626246264
const char *ext_values[] = {
4626346265
"hash",
4626446266
"hash",
4626546267
"DNS:example.com, IP:127.0.0.1",
46266-
"digitalSignature,keyEncipherment,dataEncipherment",
46268+
"digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,"
46269+
"keyAgreement,keyCertSign,cRLSign,encipherOnly,decipherOnly",
46270+
"serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,"
46271+
"OCSPSigning",
4626746272
};
4626846273
size_t i;
4626946274
X509_EXTENSION* ext = NULL;
4627046275
X509* x509 = NULL;
46276+
unsigned int keyUsageFlags;
46277+
unsigned int extKeyUsageFlags;
4627146278

4627246279
ExpectNotNull(x509 = X509_new());
4627346280

46281+
/* keyUsage / extKeyUsage should match string above */
46282+
keyUsageFlags = KU_DIGITAL_SIGNATURE
46283+
| KU_NON_REPUDIATION
46284+
| KU_KEY_ENCIPHERMENT
46285+
| KU_DATA_ENCIPHERMENT
46286+
| KU_KEY_AGREEMENT
46287+
| KU_KEY_CERT_SIGN
46288+
| KU_CRL_SIGN
46289+
| KU_ENCIPHER_ONLY
46290+
| KU_DECIPHER_ONLY;
46291+
extKeyUsageFlags = XKU_SSL_CLIENT
46292+
| XKU_SSL_SERVER
46293+
| XKU_CODE_SIGN
46294+
| XKU_SMIME
46295+
| XKU_TIMESTAMP
46296+
| XKU_OCSP_SIGN;
46297+
4627446298
for (i = 0; i < ext_names_count; i++) {
4627546299
ExpectNotNull(ext = X509V3_EXT_nconf(NULL, NULL, ext_names[i],
4627646300
ext_values[i]));
@@ -46290,6 +46314,13 @@ static int test_wolfSSL_X509V3_EXT_nconf(void)
4629046314
ExpectNotNull(ext = X509V3_EXT_nconf(NULL, NULL, ext_names[i],
4629146315
ext_values[i]));
4629246316
ExpectIntEQ(X509_add_ext(x509, ext, -1), WOLFSSL_SUCCESS);
46317+
46318+
if (ext_nids[i] == NID_key_usage) {
46319+
ExpectIntEQ(X509_get_key_usage(x509), keyUsageFlags);
46320+
}
46321+
else if (ext_nids[i] == NID_ext_key_usage) {
46322+
ExpectIntEQ(X509_get_extended_key_usage(x509), extKeyUsageFlags);
46323+
}
4629346324
X509_EXTENSION_free(ext);
4629446325
ext = NULL;
4629546326
}

wolfcrypt/src/asn.c

Lines changed: 128 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -26660,6 +26660,132 @@ int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr,
2666026660
}
2666126661
#endif /* WOLFSSL_CERT_GEN || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
2666226662

26663+
#if (defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_EXT)) || \
26664+
(defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA))
26665+
26666+
/* Convert key usage string (comma delimited, null terminated) to word16
26667+
* Returns 0 on success, negative on error */
26668+
int ParseKeyUsageStr(const char* value, word16* keyUsage, void* heap)
26669+
{
26670+
int ret = 0;
26671+
char *token, *str, *ptr;
26672+
word32 len = 0;
26673+
word16 usage = 0;
26674+
26675+
if (value == NULL || keyUsage == NULL) {
26676+
return BAD_FUNC_ARG;
26677+
}
26678+
26679+
/* duplicate string (including terminator) */
26680+
len = (word32)XSTRLEN(value);
26681+
str = (char*)XMALLOC(len + 1, heap, DYNAMIC_TYPE_TMP_BUFFER);
26682+
if (str == NULL) {
26683+
return MEMORY_E;
26684+
}
26685+
XMEMCPY(str, value, len + 1);
26686+
26687+
/* parse value, and set corresponding Key Usage value */
26688+
if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
26689+
XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
26690+
return KEYUSAGE_E;
26691+
}
26692+
while (token != NULL) {
26693+
if (!XSTRCASECMP(token, "digitalSignature"))
26694+
usage |= KEYUSE_DIGITAL_SIG;
26695+
else if (!XSTRCASECMP(token, "nonRepudiation") ||
26696+
!XSTRCASECMP(token, "contentCommitment"))
26697+
usage |= KEYUSE_CONTENT_COMMIT;
26698+
else if (!XSTRCASECMP(token, "keyEncipherment"))
26699+
usage |= KEYUSE_KEY_ENCIPHER;
26700+
else if (!XSTRCASECMP(token, "dataEncipherment"))
26701+
usage |= KEYUSE_DATA_ENCIPHER;
26702+
else if (!XSTRCASECMP(token, "keyAgreement"))
26703+
usage |= KEYUSE_KEY_AGREE;
26704+
else if (!XSTRCASECMP(token, "keyCertSign"))
26705+
usage |= KEYUSE_KEY_CERT_SIGN;
26706+
else if (!XSTRCASECMP(token, "cRLSign"))
26707+
usage |= KEYUSE_CRL_SIGN;
26708+
else if (!XSTRCASECMP(token, "encipherOnly"))
26709+
usage |= KEYUSE_ENCIPHER_ONLY;
26710+
else if (!XSTRCASECMP(token, "decipherOnly"))
26711+
usage |= KEYUSE_DECIPHER_ONLY;
26712+
else {
26713+
ret = KEYUSAGE_E;
26714+
break;
26715+
}
26716+
26717+
token = XSTRTOK(NULL, ",", &ptr);
26718+
}
26719+
26720+
XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
26721+
26722+
if (ret == 0) {
26723+
*keyUsage = usage;
26724+
}
26725+
26726+
return ret;
26727+
}
26728+
26729+
/* Convert extended key usage string (comma delimited, null terminated) to byte
26730+
* Returns 0 on success, negative on error */
26731+
int ParseExtKeyUsageStr(const char* value, byte* extKeyUsage, void* heap)
26732+
{
26733+
int ret = 0;
26734+
char *token, *str, *ptr;
26735+
word32 len = 0;
26736+
byte usage = 0;
26737+
26738+
if (value == NULL || extKeyUsage == NULL) {
26739+
return BAD_FUNC_ARG;
26740+
}
26741+
26742+
/* duplicate string (including terminator) */
26743+
len = (word32)XSTRLEN(value);
26744+
str = (char*)XMALLOC(len + 1, heap, DYNAMIC_TYPE_TMP_BUFFER);
26745+
if (str == NULL) {
26746+
return MEMORY_E;
26747+
}
26748+
XMEMCPY(str, value, len + 1);
26749+
26750+
/* parse value, and set corresponding Key Usage value */
26751+
if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
26752+
XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
26753+
return EXTKEYUSAGE_E;
26754+
}
26755+
while (token != NULL) {
26756+
if (!XSTRCASECMP(token, "any"))
26757+
usage |= EXTKEYUSE_ANY;
26758+
else if (!XSTRCASECMP(token, "serverAuth"))
26759+
usage |= EXTKEYUSE_SERVER_AUTH;
26760+
else if (!XSTRCASECMP(token, "clientAuth"))
26761+
usage |= EXTKEYUSE_CLIENT_AUTH;
26762+
else if (!XSTRCASECMP(token, "codeSigning"))
26763+
usage |= EXTKEYUSE_CODESIGN;
26764+
else if (!XSTRCASECMP(token, "emailProtection"))
26765+
usage |= EXTKEYUSE_EMAILPROT;
26766+
else if (!XSTRCASECMP(token, "timeStamping"))
26767+
usage |= EXTKEYUSE_TIMESTAMP;
26768+
else if (!XSTRCASECMP(token, "OCSPSigning"))
26769+
usage |= EXTKEYUSE_OCSP_SIGN;
26770+
else {
26771+
ret = EXTKEYUSAGE_E;
26772+
break;
26773+
}
26774+
26775+
token = XSTRTOK(NULL, ",", &ptr);
26776+
}
26777+
26778+
XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER);
26779+
26780+
if (ret == 0) {
26781+
*extKeyUsage = usage;
26782+
}
26783+
26784+
return ret;
26785+
}
26786+
26787+
#endif /* (CERT_GEN && CERT_EXT) || (OPENSSL_ALL || OPENSSL_EXTRA) */
26788+
2666326789
#ifdef WOLFSSL_CERT_GEN
2666426790
/* Encodes one attribute of the name (issuer/subject)
2666526791
* call we_EncodeName_ex with 0x16, IA5String for email type
@@ -30484,109 +30610,29 @@ int wc_SetAuthKeyId(Cert *cert, const char* file)
3048430610
int wc_SetKeyUsage(Cert *cert, const char *value)
3048530611
{
3048630612
int ret = 0;
30487-
char *token, *str, *ptr;
30488-
word32 len;
3048930613

3049030614
if (cert == NULL || value == NULL)
3049130615
return BAD_FUNC_ARG;
3049230616

3049330617
cert->keyUsage = 0;
3049430618

30495-
/* duplicate string (including terminator) */
30496-
len = (word32)XSTRLEN(value);
30497-
str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
30498-
if (str == NULL)
30499-
return MEMORY_E;
30500-
XMEMCPY(str, value, len+1);
30501-
30502-
/* parse value, and set corresponding Key Usage value */
30503-
if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
30504-
XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
30505-
return KEYUSAGE_E;
30506-
}
30507-
while (token != NULL)
30508-
{
30509-
if (!XSTRCASECMP(token, "digitalSignature"))
30510-
cert->keyUsage |= KEYUSE_DIGITAL_SIG;
30511-
else if (!XSTRCASECMP(token, "nonRepudiation") ||
30512-
!XSTRCASECMP(token, "contentCommitment"))
30513-
cert->keyUsage |= KEYUSE_CONTENT_COMMIT;
30514-
else if (!XSTRCASECMP(token, "keyEncipherment"))
30515-
cert->keyUsage |= KEYUSE_KEY_ENCIPHER;
30516-
else if (!XSTRCASECMP(token, "dataEncipherment"))
30517-
cert->keyUsage |= KEYUSE_DATA_ENCIPHER;
30518-
else if (!XSTRCASECMP(token, "keyAgreement"))
30519-
cert->keyUsage |= KEYUSE_KEY_AGREE;
30520-
else if (!XSTRCASECMP(token, "keyCertSign"))
30521-
cert->keyUsage |= KEYUSE_KEY_CERT_SIGN;
30522-
else if (!XSTRCASECMP(token, "cRLSign"))
30523-
cert->keyUsage |= KEYUSE_CRL_SIGN;
30524-
else if (!XSTRCASECMP(token, "encipherOnly"))
30525-
cert->keyUsage |= KEYUSE_ENCIPHER_ONLY;
30526-
else if (!XSTRCASECMP(token, "decipherOnly"))
30527-
cert->keyUsage |= KEYUSE_DECIPHER_ONLY;
30528-
else {
30529-
ret = KEYUSAGE_E;
30530-
break;
30531-
}
30532-
30533-
token = XSTRTOK(NULL, ",", &ptr);
30534-
}
30619+
ret = ParseKeyUsageStr(value, &cert->keyUsage, cert->heap);
3053530620

30536-
XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
3053730621
return ret;
3053830622
}
3053930623

3054030624
/* Set ExtendedKeyUsage from human readable string */
3054130625
int wc_SetExtKeyUsage(Cert *cert, const char *value)
3054230626
{
3054330627
int ret = 0;
30544-
char *token, *str, *ptr;
30545-
word32 len;
3054630628

3054730629
if (cert == NULL || value == NULL)
3054830630
return BAD_FUNC_ARG;
3054930631

3055030632
cert->extKeyUsage = 0;
3055130633

30552-
/* duplicate string (including terminator) */
30553-
len = (word32)XSTRLEN(value);
30554-
str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
30555-
if (str == NULL)
30556-
return MEMORY_E;
30557-
XMEMCPY(str, value, len+1);
30558-
30559-
/* parse value, and set corresponding Key Usage value */
30560-
if ((token = XSTRTOK(str, ",", &ptr)) == NULL) {
30561-
XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
30562-
return EXTKEYUSAGE_E;
30563-
}
30564-
30565-
while (token != NULL)
30566-
{
30567-
if (!XSTRCASECMP(token, "any"))
30568-
cert->extKeyUsage |= EXTKEYUSE_ANY;
30569-
else if (!XSTRCASECMP(token, "serverAuth"))
30570-
cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH;
30571-
else if (!XSTRCASECMP(token, "clientAuth"))
30572-
cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH;
30573-
else if (!XSTRCASECMP(token, "codeSigning"))
30574-
cert->extKeyUsage |= EXTKEYUSE_CODESIGN;
30575-
else if (!XSTRCASECMP(token, "emailProtection"))
30576-
cert->extKeyUsage |= EXTKEYUSE_EMAILPROT;
30577-
else if (!XSTRCASECMP(token, "timeStamping"))
30578-
cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP;
30579-
else if (!XSTRCASECMP(token, "OCSPSigning"))
30580-
cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN;
30581-
else {
30582-
ret = EXTKEYUSAGE_E;
30583-
break;
30584-
}
30585-
30586-
token = XSTRTOK(NULL, ",", &ptr);
30587-
}
30634+
ret = ParseExtKeyUsageStr(value, &cert->extKeyUsage, cert->heap);
3058830635

30589-
XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER);
3059030636
return ret;
3059130637
}
3059230638

0 commit comments

Comments
 (0)