diff --git a/src/ssl.c b/src/ssl.c index f7c2b3aad..9bec536c9 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -17790,16 +17790,24 @@ int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name) byte* in, int* inOutSz) { WOLFSSL_ENTER("wolfSSL_X509_get_serial_number"); - if (x509 == NULL || in == NULL || - inOutSz == NULL || *inOutSz < x509->serialSz) + if (x509 == NULL || inOutSz == NULL) { + WOLFSSL_MSG("Null argument passed in"); return BAD_FUNC_ARG; + } - XMEMCPY(in, x509->serial, x509->serialSz); + if (in != NULL) { + if (*inOutSz < x509->serialSz) { + WOLFSSL_MSG("Serial buffer too small"); + return BUFFER_E; + } + XMEMCPY(in, x509->serial, x509->serialSz); + } *inOutSz = x509->serialSz; return WOLFSSL_SUCCESS; } + /* not an openssl compatibility function - getting for derCert */ const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz) { @@ -37150,167 +37158,38 @@ void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) } #if defined(WOLFSSL_CERT_GEN) + /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to + * a Cert structure. + * + * returns length of DER on success and a negative error value on failure + */ + static int CopyX509NameToCert(WOLFSSL_X509_NAME* n, byte* out) + { + unsigned char* der = NULL; + int length = BAD_FUNC_ARG, ret = BAD_FUNC_ARG; + word32 idx = 0; -/* helper function for CopyX509NameToCertName() - * - * returns WOLFSSL_SUCCESS on success - */ -static int CopyX509NameEntry(char* out, int mx, WOLFSSL_X509_NAME* name, - int nid, byte* transfered) -{ - int inLen = 0; - unsigned char* in = NULL; - int i; - - if (nid == ASN_COUNTRY_NAME) - nid = NID_countryName; - if (nid == ASN_EMAIL_NAME) - nid = NID_emailAddress; - - for (i = 0; i < MAX_NAME_ENTRIES; i++) { - if (name->entry[i].set && name->entry[i].nid == nid) { - in = wolfSSL_ASN1_STRING_data(name->entry[i].value); - inLen = wolfSSL_ASN1_STRING_length(name->entry[i].value); - transfered[i] = 1; - break; - } - } - - if (in == NULL) { - /* entry type not found */ - return WOLFSSL_FAILURE; - } - - if (inLen > mx) { - WOLFSSL_MSG("Name too long"); - XMEMCPY(out, in, mx); - } - else { - XMEMCPY(out, in, inLen); - out[inLen] = '\0'; - } - - /* make sure is null terminated */ - out[mx-1] = '\0'; - - return WOLFSSL_SUCCESS; -} - - -#ifdef WOLFSSL_MULTI_ATTRIB -/* 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; - } -} -#endif /* WOLFSSL_MULTI_ATTRIB */ - - -/* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to - * a CertName structure. - * - * returns WOLFSSL_SUCCESS on success and a negative error value on failure - */ -static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) -{ - int idx = 0; -#ifdef WOLFSSL_MULTI_ATTRIB - int i, j = 0; -#endif - int count = 0; - const char* current; - byte transferred[MAX_NAME_ENTRIES] = {0}; - - if (n == NULL || cName == NULL) { - return BAD_FUNC_ARG; - } - - /* initialize cert name */ - cName->country[0] = '\0'; - cName->countryEnc = CTC_PRINTABLE; - cName->state[0] = '\0'; - cName->stateEnc = CTC_UTF8; - cName->locality[0] = '\0'; - cName->localityEnc = CTC_UTF8; - cName->sur[0] = '\0'; - cName->surEnc = CTC_UTF8; - cName->org[0] = '\0'; - cName->orgEnc = CTC_UTF8; - cName->unit[0] = '\0'; - cName->unitEnc = CTC_UTF8; - cName->commonName[0] = '\0'; - cName->commonNameEnc = CTC_UTF8; - cName->serialDev[0] = '\0'; - cName->serialDevEnc = CTC_PRINTABLE; -#ifdef WOLFSSL_CERT_EXT - cName->busCat[0] = '\0'; - cName->busCatEnc = CTC_UTF8; - cName->joiC[0] = '\0'; - cName->joiCEnc = CTC_PRINTABLE; - cName->joiSt[0] = '\0'; - cName->joiStEnc = CTC_PRINTABLE; -#endif - cName->email[0] = '\0'; - - current = GetOneCertName(cName, idx); - while (current != NULL) { - if (CopyX509NameEntry((char*)current, CTC_NAME_SIZE, n, - GetCertNameId(idx), transferred) == SSL_SUCCESS) { - count++; + ret = wolfSSL_i2d_X509_NAME(n, &der); + if (ret > (int)sizeof(CertName) || ret < 0) { + WOLFSSL_MSG("Name conversion error"); + ret = MEMORY_E; } - idx++; - current = GetOneCertName(cName, idx); - } - -#ifdef WOLFSSL_MULTI_ATTRIB - /* copy over multiple entries */ - idx = wolfSSL_X509_NAME_entry_count(n); - for (i = 0; i < MAX_NAME_ENTRIES && count < idx; i++) { - /* entry is set but was not yet transferred over */ - if (n->entry[i].set && transferred[i] == 0) { - unsigned char* data; - int length; - - WOLFSSL_X509_NAME_ENTRY* e = &n->entry[i]; - - data = wolfSSL_ASN1_STRING_data(e->value); - length = wolfSSL_ASN1_STRING_length(e->value); - - if (j >= CTC_MAX_ATTRIB) { - WOLFSSL_MSG("No more space left in CertName"); - break; - } - - cName->name[j].sz = length; - cName->name[j].type = CTC_UTF8; - cName->name[j].id = ConvertNIDToWolfSSL(e->nid); - XMEMCPY(cName->name[j].value, data, length); - - j++; - count++; + if (ret > 0) { + /* strip off sequence, this gets added on certificate creation */ + ret = GetSequence(der, &idx, &length, ret); } - } -#endif /* WOLFSSL_MULTI_ATTRIB */ + if (ret > 0) { + XMEMCPY(out, der + idx, length); + } + + if (der != NULL) + XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL); + + return length; + } - return WOLFSSL_SUCCESS; -} #ifdef WOLFSSL_CERT_REQ static int ReqCertFromX509(Cert* cert, WOLFSSL_X509* req) @@ -37320,7 +37199,16 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) if (wc_InitCert(cert) != 0) return WOLFSSL_FAILURE; - ret = CopyX509NameToCertName(&req->subject, &cert->subject); + + ret = CopyX509NameToCert(&(req->subject), cert->sbjRaw); + if (ret < 0) { + WOLFSSL_MSG("REQ subject conversion error"); + ret = MEMORY_E; + } + else { + ret = WOLFSSL_SUCCESS; + } + if (ret == WOLFSSL_SUCCESS) { cert->version = req->version; cert->isCA = req->isCa; @@ -37338,6 +37226,26 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) return ret; } #endif +#ifdef WOLFSSL_ALT_NAMES + /* converts WOLFSSL_AN1_TIME to Cert form, returns positive size on + * success */ + static int CertDateFromX509(byte* out, int outSz, WOLFSSL_ASN1_TIME* t) + { + int sz, i; + + if (t->length + 1 >= outSz) { + return BUFFER_E; + } + + out[0] = t->type; + sz = SetLength(t->length - 1, out + 1) + 1; /* gen tag */ + for (i = 0; i < t->length - 1; i++) { + out[sz + i] = t->data[i]; + } + return t->length - 1 + sz; + } +#endif + /* convert a WOLFSSL_X509 to a Cert structure for writing out */ static int CertFromX509(Cert* cert, WOLFSSL_X509* x509) @@ -37359,31 +37267,22 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) #ifdef WOLFSSL_ALT_NAMES if (x509->notBefore.length > 0) { - if ((x509->notBefore.length + 2) < CTC_DATE_SIZE) { - cert->beforeDate[0] = x509->notBefore.type; - cert->beforeDate[1] = x509->notBefore.length; - XMEMCPY(&cert->beforeDate[2], x509->notBefore.data, - x509->notBefore.length); - cert->beforeDateSz = x509->notBefore.length + 2; - } - else { - WOLFSSL_MSG("Not before date too large"); + cert->beforeDateSz = CertDateFromX509(cert->beforeDate, + CTC_DATE_SIZE, &x509->notBefore); + if (cert->beforeDateSz <= 0){ + WOLFSSL_MSG("Not before date error"); return WOLFSSL_FAILURE; } } else { cert->beforeDateSz = 0; } + if (x509->notAfter.length > 0) { - if ((x509->notAfter.length + 2) < CTC_DATE_SIZE) { - cert->afterDate[0] = x509->notAfter.type; - cert->afterDate[1] = x509->notAfter.length; - XMEMCPY(&cert->afterDate[2], x509->notAfter.data, - x509->notAfter.length); - cert->afterDateSz = x509->notAfter.length + 2; - } - else { - WOLFSSL_MSG("Not after date too large"); + cert->afterDateSz = CertDateFromX509(cert->afterDate, + CTC_DATE_SIZE, &x509->notAfter); + if (cert->afterDateSz <= 0){ + WOLFSSL_MSG("Not after date error"); return WOLFSSL_FAILURE; } } @@ -37440,29 +37339,41 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) XMEMCPY(cert->challengePw, x509->challengePw, CTC_NAME_SIZE); #endif - if (x509->serialSz <= CTC_SERIAL_SIZE) { - XMEMCPY(cert->serial, x509->serial, x509->serialSz); - } - else { - WOLFSSL_MSG("Serial size error"); - return WOLFSSL_FAILURE; + /* set serial number */ + if (x509->serialSz > 0) { + byte serial[EXTERNAL_SERIAL_SIZE]; + int serialSz = EXTERNAL_SERIAL_SIZE; + + ret = wolfSSL_X509_get_serial_number(x509, serial, &serialSz); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Serial size error"); + return WOLFSSL_FAILURE; + } + XMEMCPY(cert->serial, serial, serialSz); + cert->serialSz = serialSz; } /* copy over Name structures */ if (x509->issuerSet) cert->selfSigned = 0; - if ((ret = CopyX509NameToCertName(&(x509->issuer), &(cert->issuer))) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error copying over issuer names"); - WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret); - return WOLFSSL_FAILURE; + + ret = CopyX509NameToCert(&(x509->subject), cert->sbjRaw); + if (ret < 0) { + WOLFSSL_MSG("Subject conversion error"); + return MEMORY_E; } - if ((ret = CopyX509NameToCertName(&(x509->subject), &(cert->subject))) - != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("Error copying over subject names"); - WOLFSSL_LEAVE("wolfSSL_X509_to_Cert()", ret); - return WOLFSSL_FAILURE; + + if (cert->selfSigned) { + XMEMCPY(cert->issRaw, cert->sbjRaw, sizeof(CertName)); } + else { + ret = CopyX509NameToCert(&(x509->issuer), cert->issRaw); + if (ret < 0) { + WOLFSSL_MSG("Issuer conversion error"); + return MEMORY_E; + } + } + cert->heap = x509->heap; @@ -37632,13 +37543,26 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) ret = wc_MakeCert_ex(&cert, der, *derSz, type, key, &rng); wc_FreeRng(&rng); } - if (ret < 0) { - return ret; - } - if ((x509->serialSz == 0) && (cert.serialSz <= EXTERNAL_SERIAL_SIZE)) { - XMEMCPY(x509->serial, cert.serial, cert.serialSz); - x509->serialSz = cert.serialSz; + if ((ret > 0) && (x509->serialSz == 0) && + (cert.serialSz <= EXTERNAL_SERIAL_SIZE) && + (cert.serialSz > 0)) { + WOLFSSL_ASN1_INTEGER *i = wolfSSL_ASN1_INTEGER_new(); + + if (i == NULL) { + ret = MEMORY_E; + } + else { + i->length = cert.serialSz + 2; + i->data[0] = ASN_INTEGER; + i->data[1] = cert.serialSz; + XMEMCPY(i->data + 2, cert.serial, cert.serialSz); + if (wolfSSL_X509_set_serialNumber(x509, i) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Issue setting generated serial number"); + ret = EXTENSIONS_E; + } + wolfSSL_ASN1_INTEGER_free(i); + } } /* Dispose of the public key object. */ @@ -37650,9 +37574,14 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) if (x509->pubKeyOID == ECDSAk) wc_ecc_free(&ecc); #endif - *derSz = ret; - return WOLFSSL_SUCCESS; + if (ret > 0) { + *derSz = ret; + return WOLFSSL_SUCCESS; + } + else { + return ret; + } } @@ -37719,12 +37648,18 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) return ret; } + + #ifndef WC_MAX_X509_GEN + /* able to override max size until dynamic buffer created */ + #define WC_MAX_X509_GEN 4096 + #endif + /* returns the size of signature on success */ int wolfSSL_X509_sign(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_MD* md) { int ret; - byte der[4096]; /* @TODO dynamic set based on expected cert size */ + byte der[WC_MAX_X509_GEN]; /* @TODO dynamic based on expected cert size */ int derSz = sizeof(der); WOLFSSL_ENTER("wolfSSL_X509_sign"); @@ -37749,53 +37684,6 @@ static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) return ret; } - - - /* 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) - { - CertName cName; - unsigned char buf[256]; /* ASN_MAX_NAME */ - int sz; - WOLFSSL_ENTER("wolfSSL_i2d_X509_NAME"); - - if (out == NULL || name == NULL) { - return BAD_FUNC_ARG; - } - XMEMSET(&cName, 0, sizeof(CertName)); - - if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) { - WOLFSSL_MSG("Error converting x509 name to internal CertName"); - return SSL_FATAL_ERROR; - } - - sz = SetName(buf, sizeof(buf), &cName); - if (sz < 0) { - return sz; - } - - /* using buffer passed in */ - if (*out != NULL) { - XMEMCPY(*out, buf, sz); - *out += sz; - } - else { - *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); - if (*out == NULL) { - return MEMORY_E; - } - XMEMCPY(*out, buf, sz); - } - - return sz; - } #endif /* WOLFSSL_CERT_GEN */ #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) @@ -48303,7 +48191,10 @@ int wolfSSL_X509_set_notAfter(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t) return WOLFSSL_FAILURE; } - XMEMCPY(&x509->notAfter, t, sizeof(WOLFSSL_ASN1_TIME)); + x509->notAfter.type = t->type; + x509->notAfter.length = t->length; + + XMEMCPY(x509->notAfter.data, t->data, CTC_DATE_SIZE); return WOLFSSL_SUCCESS; } @@ -48314,7 +48205,10 @@ int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t) return WOLFSSL_FAILURE; } - XMEMCPY(&x509->notBefore, t, sizeof(WOLFSSL_ASN1_TIME)); + x509->notBefore.type = t->type; + x509->notBefore.length = t->length; + + XMEMCPY(x509->notBefore.data, t->data, CTC_DATE_SIZE); return WOLFSSL_SUCCESS; } @@ -48322,16 +48216,16 @@ int wolfSSL_X509_set_notBefore(WOLFSSL_X509* x509, const WOLFSSL_ASN1_TIME* t) int wolfSSL_X509_set_serialNumber(WOLFSSL_X509* x509, WOLFSSL_ASN1_INTEGER* s) { WOLFSSL_ENTER("wolfSSL_X509_set_serialNumber"); - if (!x509 || !s || s->dataMax >= EXTERNAL_SERIAL_SIZE) + if (!x509 || !s || s->length >= EXTERNAL_SERIAL_SIZE) return WOLFSSL_FAILURE; - if (s->isDynamic) - XSTRNCPY((char*)x509->serial,(char*)s->data,s->dataMax); - else - XSTRNCPY((char*)x509->serial,(char*)s->intData,s->dataMax); - - x509->serial[s->dataMax] = 0; - x509->serialSz = s->dataMax; + /* WOLFSSL_ASN1_INTEGER has type | size | data */ + if (s->length < 3) { + return WOLFSSL_FAILURE; + } + XMEMCPY(x509->serial, s->data + 2, s->length - 2); + x509->serialSz = s->length - 2; + x509->serial[s->length] = 0; return WOLFSSL_SUCCESS; } diff --git a/tests/api.c b/tests/api.c index 2a9fe5efd..0e991e8a2 100644 --- a/tests/api.c +++ b/tests/api.c @@ -27731,20 +27731,26 @@ static void test_wolfSSL_X509_sign(void) #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) int ret; + char *caSubject; X509_NAME *name; - X509 *x509; + X509 *x509, *ca; + DecodedCert dCert; EVP_PKEY *pub; EVP_PKEY *priv; #if defined(USE_CERT_BUFFERS_1024) const unsigned char* rsaPriv = client_key_der_1024; const unsigned char* rsaPub = client_keypub_der_1024; + const unsigned char* certIssuer = client_cert_der_1024; long clientKeySz = (long)sizeof_client_key_der_1024; long clientPubKeySz = (long)sizeof_client_keypub_der_1024; + long certIssuerSz = (long)sizeof_client_cert_der_1024; #elif defined(USE_CERT_BUFFERS_2048) const unsigned char* rsaPriv = client_key_der_2048; const unsigned char* rsaPub = client_keypub_der_2048; + const unsigned char* certIssuer = client_cert_der_2048; long clientKeySz = (long)sizeof_client_key_der_2048; long clientPubKeySz = (long)sizeof_client_keypub_der_2048; + long certIssuerSz = (long)sizeof_client_cert_der_2048; #endif byte sn[16]; int snSz = sizeof(sn); @@ -27769,6 +27775,7 @@ static void test_wolfSSL_X509_sign(void) AssertIntNE(X509_set_version(x509, 2L), 0); /* Set subject name, add pubkey, and sign certificate */ AssertIntEQ(X509_set_subject_name(x509, name), SSL_SUCCESS); + X509_NAME_free(name); AssertIntEQ(X509_set_pubkey(x509, pub), SSL_SUCCESS); #ifdef WOLFSSL_ALT_NAMES /* Add some subject alt names */ @@ -27817,7 +27824,7 @@ static void test_wolfSSL_X509_sign(void) } XFCLOSE(tmpFile); #endif - + /* Variation in size depends on ASN.1 encoding when MSB is set */ #ifndef WOLFSSL_ALT_NAMES /* Valid case - size should be 798-797 with 16 byte serial number */ @@ -27829,6 +27836,35 @@ static void test_wolfSSL_X509_sign(void) /* Valid case - size should be 926-927 with 16 byte serial number */ AssertTrue((ret == 910 + snSz) || (ret == 911 + snSz)); #endif + /* check that issuer name is as expected after signature */ + InitDecodedCert(&dCert, certIssuer, (word32)certIssuerSz, 0); + AssertIntEQ(ParseCert(&dCert, CERT_TYPE, NO_VERIFY, NULL), 0); + + AssertNotNull(ca = wolfSSL_d2i_X509(NULL, &certIssuer, (int)certIssuerSz)); + AssertNotNull(caSubject = wolfSSL_X509_NAME_oneline( + X509_get_subject_name(ca), 0, 0)); + AssertIntEQ(0, XSTRNCMP(caSubject, dCert.subject, XSTRLEN(caSubject))); + free(caSubject); + +#ifdef WOLFSSL_MULTI_ATTRIB + /* test adding multiple OU's to the signer */ + AssertNotNull(name = X509_get_subject_name(ca)); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_UTF8, + (byte*)"OU1", 3, -1, 0), SSL_SUCCESS); + AssertIntEQ(X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_UTF8, + (byte*)"OU2", 3, -1, 0), SSL_SUCCESS); + AssertIntGT(X509_sign(ca, priv, EVP_sha256()), 0); +#endif + + AssertNotNull(name = X509_get_subject_name(ca)); + AssertIntEQ(X509_set_issuer_name(x509, name), SSL_SUCCESS); + + AssertIntGT(X509_sign(x509, priv, EVP_sha256()), 0); + AssertNotNull(caSubject = wolfSSL_X509_NAME_oneline( + X509_get_issuer_name(x509), 0, 0)); + free(caSubject); + + FreeDecodedCert(&dCert); /* Test invalid parameters */ AssertIntEQ(X509_sign(NULL, priv, EVP_sha256()), 0); @@ -27844,10 +27880,11 @@ static void test_wolfSSL_X509_sign(void) AssertIntEQ(X509_get_ext_count(x509), SSL_FAILURE); #endif - X509_NAME_free(name); + EVP_PKEY_free(priv); EVP_PKEY_free(pub); X509_free(x509); + X509_free(ca); printf(resultFmt, passed); #endif @@ -30653,6 +30690,8 @@ static void test_wolfSSL_X509_get_serialNumber(void) BIGNUM* bn; X509* x509; char *serialHex; + byte serial[3]; + int serialSz; printf(testingFmt, "wolfSSL_X509_get_serialNumber()"); @@ -30663,6 +30702,40 @@ static void test_wolfSSL_X509_get_serialNumber(void) /* check on value of ASN1 Integer */ AssertNotNull(bn = ASN1_INTEGER_to_BN(a, NULL)); + + /* test setting serial number and then retrieving it */ + AssertNotNull(a = ASN1_INTEGER_new()); + ASN1_INTEGER_set(a, 3); + AssertIntEQ(X509_set_serialNumber(x509, a), WOLFSSL_SUCCESS); + serialSz = sizeof(serial); + AssertIntEQ(wolfSSL_X509_get_serial_number(x509, serial, &serialSz), + WOLFSSL_SUCCESS); + AssertIntEQ(serialSz, 1); + AssertIntEQ(serial[0], 3); + ASN1_INTEGER_free(a); + + /* test setting serial number with 0's in it */ + serial[0] = 0x01; + serial[1] = 0x00; + serial[2] = 0x02; + + AssertNotNull(a = wolfSSL_ASN1_INTEGER_new()); + a->data[0] = ASN_INTEGER; + a->data[1] = sizeof(serial); + XMEMCPY(&a->data[2], serial, sizeof(serial)); + a->length = sizeof(serial) + 2; + AssertIntEQ(X509_set_serialNumber(x509, a), WOLFSSL_SUCCESS); + + XMEMSET(serial, 0, sizeof(serial)); + serialSz = sizeof(serial); + AssertIntEQ(wolfSSL_X509_get_serial_number(x509, serial, &serialSz), + WOLFSSL_SUCCESS); + AssertIntEQ(serialSz, 3); + AssertIntEQ(serial[0], 0x01); + AssertIntEQ(serial[1], 0x00); + AssertIntEQ(serial[2], 0x02); + ASN1_INTEGER_free(a); + X509_free(x509); /* free's a */ AssertNotNull(serialHex = BN_bn2hex(bn)); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 51aec48ae..53c35045f 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -5658,6 +5658,7 @@ int GetName(DecodedCert* cert, int nameType, int maxIdx) #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \ && !defined(WOLFCRYPT_ONLY) int nid = NID_undef; + int enc; #endif /* OPENSSL_EXTRA */ if (GetSet(cert->source, &cert->srcIdx, &dummy, maxIdx) < 0) { @@ -6048,8 +6049,20 @@ int GetName(DecodedCert* cert, int nameType, int maxIdx) } #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ !defined(WOLFCRYPT_ONLY) + switch (b) { + case CTC_UTF8: + enc = MBSTRING_UTF8; + break; + case CTC_PRINTABLE: + enc = V_ASN1_PRINTABLESTRING; + break; + default: + WOLFSSL_MSG("Unknown encoding type, using UTF8 by default"); + enc = MBSTRING_UTF8; + } + if (nid != NID_undef) { - if (wolfSSL_X509_NAME_add_entry_by_NID(dName, nid, MBSTRING_UTF8, + if (wolfSSL_X509_NAME_add_entry_by_NID(dName, nid, enc, &cert->source[cert->srcIdx], strLen, -1, -1) != WOLFSSL_SUCCESS) { wolfSSL_X509_NAME_free(dName); @@ -12718,6 +12731,149 @@ static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, return idx; } + +#if 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; + + 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 */ + + /* encode CertName into output, return total bytes written */ int SetName(byte* output, word32 outputSz, CertName* name) { @@ -12977,7 +13133,7 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, } /* subject name */ -#ifdef WOLFSSL_CERT_EXT +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) if (XSTRLEN((const char*)cert->sbjRaw) > 0) { /* Use the raw subject */ int idx; @@ -13005,13 +13161,14 @@ static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, return SUBJECT_E; /* issuer name */ -#ifdef WOLFSSL_CERT_EXT +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) if (XSTRLEN((const char*)cert->issRaw) > 0) { /* Use the raw issuer */ int idx; der->issuerSz = min(sizeof(der->issuer), (word32)XSTRLEN((const char*)cert->issRaw)); + /* header */ idx = SetSequence(der->issuerSz, der->issuer); if (der->issuerSz + idx > (int)sizeof(der->issuer)) { @@ -13601,7 +13758,29 @@ static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, der->versionSz = SetMyVersion(cert->version, der->version, FALSE); /* subject name */ - der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject); +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) + if (XSTRLEN((const char*)cert->sbjRaw) > 0) { + /* Use the raw subject */ + int idx; + + der->subjectSz = min(sizeof(der->subject), + (word32)XSTRLEN((const char*)cert->sbjRaw)); + /* header */ + idx = SetSequence(der->subjectSz, der->subject); + if (der->subjectSz + idx > (int)sizeof(der->subject)) { + return SUBJECT_E; + } + + XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw, + der->subjectSz); + der->subjectSz += idx; + } + else +#endif + { + der->subjectSz = SetName(der->subject, sizeof(der->subject), + &cert->subject); + } if (der->subjectSz <= 0) return SUBJECT_E; diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 3f111d445..a1c41eb49 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -6645,13 +6645,14 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap) #else ret = wc_InitRng(&pkey->rng); #endif + pkey->references = 1; + wc_InitMutex(&pkey->refMutex); /* init of mutex needs to come before + * wolfSSL_EVP_PKEY_free */ if (ret != 0){ wolfSSL_EVP_PKEY_free(pkey); WOLFSSL_MSG("memory failure"); return NULL; } - pkey->references = 1; - wc_InitMutex(&pkey->refMutex); } else { WOLFSSL_MSG("memory failure"); diff --git a/wolfssl/openssl/asn1.h b/wolfssl/openssl/asn1.h index b957678c5..f9f806b89 100644 --- a/wolfssl/openssl/asn1.h +++ b/wolfssl/openssl/asn1.h @@ -69,6 +69,7 @@ #define V_ASN1_OBJECT 6 #define V_ASN1_UTCTIME 23 #define V_ASN1_GENERALIZEDTIME 24 +#define V_ASN1_PRINTABLESTRING 19 #define ASN1_STRING_FLAG_BITS_LEFT 0x008 #define ASN1_STRING_FLAG_NDEF 0x010 diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index e37de4ab5..6ca38a589 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -366,7 +366,6 @@ enum Misc_ASN { MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif MAX_AIA_SZ = 2, /* Max Authority Info Access extension size*/ - MAX_NAME_ENTRIES = 13, /* entries added to x509 name struct */ OCSP_NONCE_EXT_SZ = 35, /* OCSP Nonce Extension size */ MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ @@ -395,6 +394,12 @@ enum Misc_ASN { PEM_LINE_LEN = PEM_LINE_SZ + 12, /* PEM line max + fudge */ }; +#ifndef WC_MAX_NAME_ENTRIES + /* entries added to x509 name struct */ + #define WC_MAX_NAME_ENTRIES 13 +#endif +#define MAX_NAME_ENTRIES WC_MAX_NAME_ENTRIES + enum Oid_Types { oidHashType = 0, diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index f5a29435d..e0024c922 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -330,6 +330,8 @@ typedef struct Cert { #endif char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; word16 certPoliciesNb; /* Number of Cert Policy */ +#endif +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) byte issRaw[sizeof(CertName)]; /* raw issuer info */ byte sbjRaw[sizeof(CertName)]; /* raw subject info */ #endif