Merge pull request #3817 from SparkiDev/i2d_x509_name_mv

ASN: move wolfSSL_i2d_X509_NAME to ssl.c
This commit is contained in:
toddouska
2021-02-25 16:03:30 -08:00
committed by GitHub
3 changed files with 278 additions and 263 deletions

170
src/ssl.c
View File

@ -40803,7 +40803,177 @@ cleanup:
return wolfSSL_X509_sign(x509, ctx->pctx->pkey, wolfSSL_EVP_MD_CTX_md(ctx)); return wolfSSL_X509_sign(x509, ctx->pctx->pkey, wolfSSL_EVP_MD_CTX_md(ctx));
} }
#endif /* OPENSSL_EXTRA */ #endif /* OPENSSL_EXTRA */
/* Guarded by either
* A) WOLFSSL_WPAS_SMALL is on or
* B) (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_CERT_GEN +
* (WOLFSSL_CERT_REQ or WOLFSSL_CERT_EXT or OPENSSL_EXTRA) has been
* defined
*/
#if defined(WOLFSSL_WPAS_SMALL) || \
(defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
defined(WOLFSSL_CERT_GEN) && \
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \
defined(OPENSSL_EXTRA))
/* Converts from NID_* value to wolfSSL value if needed */
static int ConvertNIDToWolfSSL(int nid)
{
switch (nid) {
case NID_commonName : return ASN_COMMON_NAME;
case NID_surname : return ASN_SUR_NAME;
case NID_countryName: return ASN_COUNTRY_NAME;
case NID_localityName: return ASN_LOCALITY_NAME;
case NID_stateOrProvinceName: return ASN_STATE_NAME;
case NID_organizationName: return ASN_ORG_NAME;
case NID_organizationalUnitName: return ASN_ORGUNIT_NAME;
case NID_emailAddress: return ASN_EMAIL_NAME;
case NID_serialNumber: return ASN_SERIAL_NUMBER;
case NID_businessCategory: return ASN_BUS_CAT;
case NID_domainComponent: return ASN_DOMAIN_COMPONENT;
default:
WOLFSSL_MSG("Attribute NID not found");
return -1;
}
}
/* Converts the x509 name structure into DER format.
*
* out pointer to either a pre setup buffer or a pointer to null for
* creating a dynamic buffer. In the case that a pre-existing buffer is
* used out will be incremented the size of the DER buffer on success.
*
* returns the size of the buffer on success, or negative value with failure
*/
int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out)
{
int totalBytes = 0, i, idx;
byte temp[MAX_SEQ_SZ];
byte *output, *local = NULL;
#ifdef WOLFSSL_SMALL_STACK
EncodedName* names = NULL;
#else
EncodedName names[MAX_NAME_ENTRIES];
#endif
if (out == NULL || name == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (names == NULL)
return MEMORY_E;
#endif
XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES);
for (i = 0; i < MAX_NAME_ENTRIES; i++) {
WOLFSSL_X509_NAME_ENTRY* entry;
int ret;
entry = wolfSSL_X509_NAME_get_entry(name, i);
if (entry != NULL && entry->set == 1) {
const char* nameStr;
int type;
WOLFSSL_ASN1_STRING* data;
data = wolfSSL_X509_NAME_ENTRY_get_data(entry);
if (data == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("Error getting entry data");
return WOLFSSL_FATAL_ERROR;
}
nameStr = (const char*)wolfSSL_ASN1_STRING_data(data);
type = wolfSSL_ASN1_STRING_type(data);
switch (type) {
case MBSTRING_UTF8:
type = CTC_UTF8;
break;
case V_ASN1_PRINTABLESTRING:
type = CTC_PRINTABLE;
break;
default:
WOLFSSL_MSG("Unknown encoding type conversion UTF8 by default");
type = CTC_UTF8;
}
ret = wc_EncodeName(&names[i], nameStr, type,
ConvertNIDToWolfSSL(entry->nid));
if (ret < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("EncodeName failed");
return WOLFSSL_FATAL_ERROR;
}
totalBytes += ret;
}
}
/* header */
idx = SetSequence(totalBytes, temp);
if (totalBytes + idx > ASN_NAME_MAX) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX");
return BUFFER_E;
}
/* check if using buffer passed in */
if (*out == NULL) {
*out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL,
DYNAMIC_TYPE_OPENSSL);
if (*out == NULL) {
return MEMORY_E;
}
}
output = *out;
/* header */
idx = SetSequence(totalBytes, temp);
if (totalBytes + idx > ASN_NAME_MAX) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX");
return BUFFER_E;
}
/* check if using buffer passed in */
if (*out == NULL) {
*out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL,
DYNAMIC_TYPE_OPENSSL);
if (*out == NULL) {
return MEMORY_E;
}
}
output = *out;
idx = SetSequence(totalBytes, output);
totalBytes += idx;
for (i = 0; i < MAX_NAME_ENTRIES; i++) {
if (names[i].used) {
XMEMCPY(output + idx, names[i].encoded, names[i].totalLen);
idx += names[i].totalLen;
}
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
/* used existing buffer passed in, so increment pointer */
if (local == NULL) {
*out += totalBytes;
}
return totalBytes;
}
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
#endif /* WOLFSSL_CERT_GEN */ #endif /* WOLFSSL_CERT_GEN */
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
WOLFSSL_X509_NAME *wolfSSL_d2i_X509_NAME(WOLFSSL_X509_NAME **name, WOLFSSL_X509_NAME *wolfSSL_d2i_X509_NAME(WOLFSSL_X509_NAME **name,

View File

@ -12413,16 +12413,6 @@ static int CopyValidity(byte* output, Cert* cert)
#endif #endif
/* ASN Encoded Name field */
typedef struct EncodedName {
int nameLen; /* actual string value length */
int totalLen; /* total encoded length */
int type; /* type of name */
int used; /* are we actually using this one */
byte encoded[CTC_NAME_SIZE * 2]; /* encoding */
} EncodedName;
/* Get Which Name from index */ /* Get Which Name from index */
const char* GetOneCertName(CertName* name, int idx) const char* GetOneCertName(CertName* name, int idx)
{ {
@ -13004,281 +12994,126 @@ int FlattenAltNames(byte* output, word32 outputSz, const DNS_entry* names)
* *
* returns length on success * returns length on success
*/ */
static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType,
byte type) byte type)
{ {
word32 idx = 0; word32 idx = 0;
/* bottom up */
byte firstLen[1 + MAX_LENGTH_SZ];
byte secondLen[MAX_LENGTH_SZ];
byte sequence[MAX_SEQ_SZ];
byte set[MAX_SET_SZ];
if (nameStr) { int strLen;
/* bottom up */ int thisLen;
byte firstLen[1 + MAX_LENGTH_SZ]; int firstSz, secondSz, seqSz, setSz;
byte secondLen[MAX_LENGTH_SZ];
byte sequence[MAX_SEQ_SZ];
byte set[MAX_SET_SZ];
int strLen = (int)XSTRLEN(nameStr); if (nameStr == NULL) {
int thisLen = strLen;
int firstSz, secondSz, seqSz, setSz;
if (strLen == 0) { /* no user data for this item */
name->used = 0;
return 0;
}
/* Restrict country code size */
if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
WOLFSSL_MSG("Country code size error");
return ASN_COUNTRY_SIZE_E;
}
secondSz = SetLength(strLen, secondLen);
thisLen += secondSz;
switch (type) {
case ASN_EMAIL_NAME: /* email */
thisLen += EMAIL_JOINT_LEN;
firstSz = EMAIL_JOINT_LEN;
break;
case ASN_DOMAIN_COMPONENT:
thisLen += PILOT_JOINT_LEN;
firstSz = PILOT_JOINT_LEN;
break;
default:
thisLen++; /* str type */
thisLen += JOINT_LEN;
firstSz = JOINT_LEN + 1;
}
thisLen++; /* id type */
firstSz = SetObjectId(firstSz, firstLen);
thisLen += firstSz;
seqSz = SetSequence(thisLen, sequence);
thisLen += seqSz;
setSz = SetSet(thisLen, set);
thisLen += setSz;
if (thisLen > (int)sizeof(name->encoded)) {
return BUFFER_E;
}
/* store it */
idx = 0;
/* set */
XMEMCPY(name->encoded, set, setSz);
idx += setSz;
/* seq */
XMEMCPY(name->encoded + idx, sequence, seqSz);
idx += seqSz;
/* asn object id */
XMEMCPY(name->encoded + idx, firstLen, firstSz);
idx += firstSz;
switch (type) {
case ASN_EMAIL_NAME:
{
const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
0x01, 0x09, 0x01, 0x16 };
/* email joint id */
XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
idx += (int)sizeof(EMAIL_OID);
}
break;
case ASN_DOMAIN_COMPONENT:
{
const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89,
0x93, 0xF2, 0x2C, 0x64, 0x01
};
XMEMCPY(name->encoded + idx, PILOT_OID,
sizeof(PILOT_OID));
idx += (int)sizeof(PILOT_OID);
/* id type */
name->encoded[idx++] = type;
/* str type */
name->encoded[idx++] = nameType;
}
break;
default:
name->encoded[idx++] = 0x55;
name->encoded[idx++] = 0x04;
/* id type */
name->encoded[idx++] = type;
/* str type */
name->encoded[idx++] = nameType;
}
/* second length */
XMEMCPY(name->encoded + idx, secondLen, secondSz);
idx += secondSz;
/* str value */
XMEMCPY(name->encoded + idx, nameStr, strLen);
idx += strLen;
name->type = type;
name->totalLen = idx;
name->used = 1;
}
else
name->used = 0; name->used = 0;
return 0;
}
thisLen = strLen = (int)XSTRLEN(nameStr);
if (strLen == 0) { /* no user data for this item */
name->used = 0;
return 0;
}
return idx; /* Restrict country code size */
} if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) {
WOLFSSL_MSG("Country code size error");
return ASN_COUNTRY_SIZE_E;
}
secondSz = SetLength(strLen, secondLen);
thisLen += secondSz;
switch (type) {
case ASN_EMAIL_NAME: /* email */
thisLen += EMAIL_JOINT_LEN;
firstSz = EMAIL_JOINT_LEN;
break;
case ASN_DOMAIN_COMPONENT:
thisLen += PILOT_JOINT_LEN;
firstSz = PILOT_JOINT_LEN;
break;
/* Guarded by either
* A) WOLFSSL_WPAS_SMALL is on or
* B) (OPENSSL_EXTRA or OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_CERT_GEN +
* (WOLFSSL_CERT_REQ or WOLFSSL_CERT_EXT or OPENSSL_EXTRA) has been
* defined
*/
#if defined(WOLFSSL_WPAS_SMALL) || \
(defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
defined(WOLFSSL_CERT_GEN) && \
(defined(WOLFSSL_CERT_REQ) || defined(WOLFSSL_CERT_EXT) || \
defined(OPENSSL_EXTRA))
/* Converts from NID_* value to wolfSSL value if needed */
static int ConvertNIDToWolfSSL(int nid)
{
switch (nid) {
case NID_commonName : return ASN_COMMON_NAME;
case NID_surname : return ASN_SUR_NAME;
case NID_countryName: return ASN_COUNTRY_NAME;
case NID_localityName: return ASN_LOCALITY_NAME;
case NID_stateOrProvinceName: return ASN_STATE_NAME;
case NID_organizationName: return ASN_ORG_NAME;
case NID_organizationalUnitName: return ASN_ORGUNIT_NAME;
case NID_emailAddress: return ASN_EMAIL_NAME;
case NID_serialNumber: return ASN_SERIAL_NUMBER;
case NID_businessCategory: return ASN_BUS_CAT;
case NID_domainComponent: return ASN_DOMAIN_COMPONENT;
default: default:
WOLFSSL_MSG("Attribute NID not found"); thisLen++; /* str type */
return -1; thisLen += JOINT_LEN;
firstSz = JOINT_LEN + 1;
} }
} thisLen++; /* id type */
firstSz = SetObjectId(firstSz, firstLen);
thisLen += firstSz;
seqSz = SetSequence(thisLen, sequence);
thisLen += seqSz;
setSz = SetSet(thisLen, set);
thisLen += setSz;
/* Converts the x509 name structure into DER format. if (thisLen > (int)sizeof(name->encoded)) {
*
* out pointer to either a pre setup buffer or a pointer to null for
* creating a dynamic buffer. In the case that a pre-existing buffer is
* used out will be incremented the size of the DER buffer on success.
*
* returns the size of the buffer on success, or negative value with failure
*/
int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out)
{
int totalBytes = 0, i, idx;
byte temp[MAX_SEQ_SZ];
byte *output, *local = NULL;
#ifdef WOLFSSL_SMALL_STACK
EncodedName* names = NULL;
#else
EncodedName names[MAX_NAME_ENTRIES];
#endif
if (out == NULL || name == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
names = (EncodedName*)XMALLOC(sizeof(EncodedName) * MAX_NAME_ENTRIES, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (names == NULL)
return MEMORY_E;
#endif
XMEMSET(names, 0, sizeof(EncodedName) * MAX_NAME_ENTRIES);
for (i = 0; i < MAX_NAME_ENTRIES; i++) {
WOLFSSL_X509_NAME_ENTRY* entry;
int ret;
entry = wolfSSL_X509_NAME_get_entry(name, i);
if (entry != NULL && entry->set == 1) {
const char* nameStr;
int type;
WOLFSSL_ASN1_STRING* data;
data = wolfSSL_X509_NAME_ENTRY_get_data(entry);
if (data == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("Error getting entry data");
return WOLFSSL_FATAL_ERROR;
}
nameStr = (const char*)wolfSSL_ASN1_STRING_data(data);
type = wolfSSL_ASN1_STRING_type(data);
switch (type) {
case MBSTRING_UTF8:
type = CTC_UTF8;
break;
case V_ASN1_PRINTABLESTRING:
type = CTC_PRINTABLE;
break;
default:
WOLFSSL_MSG("Unknown encoding type conversion UTF8 by default");
type = CTC_UTF8;
}
ret = wc_EncodeName(&names[i], nameStr, type,
ConvertNIDToWolfSSL(entry->nid));
if (ret < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("EncodeName failed");
return WOLFSSL_FATAL_ERROR;
}
totalBytes += ret;
}
}
/* header */
idx = SetSequence(totalBytes, temp);
if (totalBytes + idx > ASN_NAME_MAX) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
WOLFSSL_MSG("Total Bytes is greater than ASN_NAME_MAX");
return BUFFER_E; return BUFFER_E;
} }
/* check if using buffer passed in */ /* store it */
if (*out == NULL) { idx = 0;
*out = local = (unsigned char*)XMALLOC(totalBytes + idx, NULL, /* set */
DYNAMIC_TYPE_OPENSSL); XMEMCPY(name->encoded, set, setSz);
if (*out == NULL) { idx += setSz;
return MEMORY_E; /* seq */
XMEMCPY(name->encoded + idx, sequence, seqSz);
idx += seqSz;
/* asn object id */
XMEMCPY(name->encoded + idx, firstLen, firstSz);
idx += firstSz;
switch (type) {
case ASN_EMAIL_NAME:
{
const byte EMAIL_OID[] = {
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16
};
/* email joint id */
XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID));
idx += (int)sizeof(EMAIL_OID);
break;
} }
}
output = *out;
idx = SetSequence(totalBytes, output); case ASN_DOMAIN_COMPONENT:
totalBytes += idx; {
for (i = 0; i < MAX_NAME_ENTRIES; i++) { const byte PILOT_OID[] = {
if (names[i].used) { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01
XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); };
idx += names[i].totalLen;
XMEMCPY(name->encoded + idx, PILOT_OID, sizeof(PILOT_OID));
idx += (int)sizeof(PILOT_OID);
/* id type */
name->encoded[idx++] = type;
/* str type */
name->encoded[idx++] = nameType;
break;
} }
}
#ifdef WOLFSSL_SMALL_STACK default:
XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); name->encoded[idx++] = 0x55;
#endif name->encoded[idx++] = 0x04;
/* id type */
/* used existing buffer passed in, so increment pointer */ name->encoded[idx++] = type;
if (local == NULL) { /* str type */
*out += totalBytes; name->encoded[idx++] = nameType;
} }
return totalBytes; /* second length */
XMEMCPY(name->encoded + idx, secondLen, secondSz);
idx += secondSz;
/* str value */
XMEMCPY(name->encoded + idx, nameStr, strLen);
idx += strLen;
name->type = type;
name->totalLen = idx;
name->used = 1;
return idx;
} }
#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
/* encode CertName into output, return total bytes written */ /* encode CertName into output, return total bytes written */
int SetName(byte* output, word32 outputSz, CertName* name) int SetName(byte* output, word32 outputSz, CertName* name)

View File

@ -977,6 +977,14 @@ struct DecodedCert {
#endif #endif
}; };
/* ASN Encoded Name field */
typedef struct EncodedName {
int nameLen; /* actual string value length */
int totalLen; /* total encoded length */
int type; /* type of name */
int used; /* are we actually using this one */
byte encoded[CTC_NAME_SIZE * 2]; /* encoding */
} EncodedName;
#ifdef NO_SHA #ifdef NO_SHA
#define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE
@ -1163,6 +1171,8 @@ WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType); WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType);
WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn); WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn);
WOLFSSL_LOCAL int wc_EncodeName(EncodedName* name, const char* nameStr,
char nameType, byte type);
/* ASN.1 helper functions */ /* ASN.1 helper functions */
#ifdef WOLFSSL_CERT_GEN #ifdef WOLFSSL_CERT_GEN
WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name); WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name);