diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 673d89bf2..87be7b2e5 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -1250,6 +1250,7 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) cert->publicKey = 0; cert->pubKeySize = 0; cert->pubKeyStored = 0; + cert->version = 0; cert->signature = 0; cert->subjectCN = 0; cert->subjectCNLen = 0; @@ -1290,11 +1291,15 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) cert->subjectOULen = 0; cert->subjectEmail = 0; cert->subjectEmailLen = 0; - cert->beforeDate = 0; - cert->beforeDateLen = 0; - cert->afterDate = 0; - cert->afterDateLen = 0; #endif /* CYASSL_CERT_GEN */ + cert->beforeDate = NULL; + cert->beforeDateLen = 0; + cert->afterDate = NULL; + cert->afterDateLen = 0; +#ifdef OPENSSL_EXTRA + XMEMSET(&cert->issuerName, 0, sizeof(DecodedName)); + XMEMSET(&cert->subjectName, 0, sizeof(DecodedName)); +#endif /* OPENSSL_EXTRA */ #ifdef CYASSL_SEP cert->deviceTypeSz = 0; cert->deviceType = NULL; @@ -1333,12 +1338,18 @@ void FreeDecodedCert(DecodedCert* cert) XFREE(cert->hwType, cert->heap, 0); XFREE(cert->hwSerialNum, cert->heap, 0); #endif /* CYASSL_SEP */ +#ifdef OPENSSL_EXTRA + if (cert->issuerName.fullName != NULL) + XFREE(cert->issuerName.fullName, NULL, DYNAMIC_TYPE_X509); + if (cert->subjectName.fullName != NULL) + XFREE(cert->subjectName.fullName, NULL, DYNAMIC_TYPE_X509); +#endif /* OPENSSL_EXTRA */ } static int GetCertHeader(DecodedCert* cert) { - int ret = 0, version, len; + int ret = 0, len; byte serialTmp[EXTERNAL_SERIAL_SIZE]; mp_int mpi; @@ -1351,7 +1362,7 @@ static int GetCertHeader(DecodedCert* cert) return ASN_PARSE_E; cert->sigIndex = len + cert->srcIdx; - if (GetExplicitVersion(cert->source, &cert->srcIdx, &version) < 0) + if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version) < 0) return ASN_PARSE_E; if (GetInt(&mpi, cert->source, &cert->srcIdx, cert->maxIdx) < 0) @@ -1537,6 +1548,10 @@ static int GetName(DecodedCert* cert, int nameType) int dummy; char* full = (nameType == ISSUER) ? cert->issuer : cert->subject; word32 idx; + #ifdef OPENSSL_EXTRA + DecodedName* dName = + (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName; + #endif /* OPENSSL_EXTRA */ CYASSL_MSG("Getting Cert Name"); @@ -1621,6 +1636,10 @@ static int GetName(DecodedCert* cert, int nameType) idx += 4; copy = TRUE; } + #ifdef OPENSSL_EXTRA + dName->cnIdx = cert->srcIdx; + dName->cnLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_SUR_NAME) { if (!tooBig) { @@ -1628,12 +1647,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 4; copy = TRUE; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectSN = (char*)&cert->source[cert->srcIdx]; - cert->subjectSNLen = strLen; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectSN = (char*)&cert->source[cert->srcIdx]; + cert->subjectSNLen = strLen; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->snIdx = cert->srcIdx; + dName->snLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_COUNTRY_NAME) { if (!tooBig) { @@ -1641,12 +1664,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 3; copy = TRUE; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectC = (char*)&cert->source[cert->srcIdx]; - cert->subjectCLen = strLen; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectC = (char*)&cert->source[cert->srcIdx]; + cert->subjectCLen = strLen; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->cIdx = cert->srcIdx; + dName->cLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_LOCALITY_NAME) { if (!tooBig) { @@ -1654,12 +1681,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 3; copy = TRUE; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectL = (char*)&cert->source[cert->srcIdx]; - cert->subjectLLen = strLen; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectL = (char*)&cert->source[cert->srcIdx]; + cert->subjectLLen = strLen; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->lIdx = cert->srcIdx; + dName->lLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_STATE_NAME) { if (!tooBig) { @@ -1667,12 +1698,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 4; copy = TRUE; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectST = (char*)&cert->source[cert->srcIdx]; - cert->subjectSTLen = strLen; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectST = (char*)&cert->source[cert->srcIdx]; + cert->subjectSTLen = strLen; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->stIdx = cert->srcIdx; + dName->stLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_ORG_NAME) { if (!tooBig) { @@ -1680,12 +1715,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 3; copy = TRUE; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectO = (char*)&cert->source[cert->srcIdx]; - cert->subjectOLen = strLen; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectO = (char*)&cert->source[cert->srcIdx]; + cert->subjectOLen = strLen; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->oIdx = cert->srcIdx; + dName->oLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_ORGUNIT_NAME) { if (!tooBig) { @@ -1693,12 +1732,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 4; copy = TRUE; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectOU = (char*)&cert->source[cert->srcIdx]; - cert->subjectOULen = strLen; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectOU = (char*)&cert->source[cert->srcIdx]; + cert->subjectOULen = strLen; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->ouIdx = cert->srcIdx; + dName->ouLen = strLen; + #endif /* OPENSSL_EXTRA */ } else if (id == ASN_SERIAL_NUMBER) { if (!tooBig) { @@ -1706,6 +1749,10 @@ static int GetName(DecodedCert* cert, int nameType) idx += 14; copy = TRUE; } + #ifdef OPENSSL_EXTRA + dName->snIdx = cert->srcIdx; + dName->snLen = strLen; + #endif /* OPENSSL_EXTRA */ } if (copy && !tooBig) { @@ -1747,12 +1794,16 @@ static int GetName(DecodedCert* cert, int nameType) idx += 14; } -#ifdef CYASSL_CERT_GEN - if (nameType == SUBJECT) { - cert->subjectEmail = (char*)&cert->source[cert->srcIdx]; - cert->subjectEmailLen = adv; - } -#endif /* CYASSL_CERT_GEN */ + #ifdef CYASSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectEmail = (char*)&cert->source[cert->srcIdx]; + cert->subjectEmailLen = adv; + } + #endif /* CYASSL_CERT_GEN */ + #ifdef OPENSSL_EXTRA + dName->emailIdx = cert->srcIdx; + dName->emailLen = adv; + #endif /* OPENSSL_EXTRA */ if (!tooBig) { XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); @@ -1772,6 +1823,10 @@ static int GetName(DecodedCert* cert, int nameType) XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); idx += adv; } + #ifdef OPENSSL_EXTRA + dName->uidIdx = cert->srcIdx; + dName->uidLen = adv; + #endif /* OPENSSL_EXTRA */ } cert->srcIdx += adv; @@ -1779,6 +1834,131 @@ static int GetName(DecodedCert* cert, int nameType) } full[idx++] = 0; + #ifdef OPENSSL_EXTRA + { + int totalLen = 0; + + if (dName->cnLen != 0) + totalLen += dName->cnLen + 4; + if (dName->snLen != 0) + totalLen += dName->snLen + 4; + if (dName->cLen != 0) + totalLen += dName->cLen + 3; + if (dName->lLen != 0) + totalLen += dName->lLen + 3; + if (dName->stLen != 0) + totalLen += dName->stLen + 4; + if (dName->oLen != 0) + totalLen += dName->oLen + 3; + if (dName->ouLen != 0) + totalLen += dName->ouLen + 4; + if (dName->emailLen != 0) + totalLen += dName->emailLen + 14; + if (dName->uidLen != 0) + totalLen += dName->uidLen + 5; + if (dName->serialLen != 0) + totalLen += dName->serialLen + 14; + + dName->fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509); + if (dName->fullName != NULL) { + idx = 0; + + if (dName->cnLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/CN=", 4); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->cnIdx], dName->cnLen); + dName->cnIdx = idx; + idx += dName->cnLen; + } + if (dName->snLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/SN=", 4); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->snIdx], dName->snLen); + dName->snIdx = idx; + idx += dName->snLen; + } + if (dName->cLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/C=", 3); + idx += 3; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->cIdx], dName->cLen); + dName->cIdx = idx; + idx += dName->cLen; + } + if (dName->lLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/L=", 3); + idx += 3; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->lIdx], dName->lLen); + dName->lIdx = idx; + idx += dName->lLen; + } + if (dName->stLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/ST=", 4); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->stIdx], dName->stLen); + dName->stIdx = idx; + idx += dName->stLen; + } + if (dName->oLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/O=", 3); + idx += 3; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->oIdx], dName->oLen); + dName->oIdx = idx; + idx += dName->oLen; + } + if (dName->ouLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/OU=", 4); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->ouIdx], dName->ouLen); + dName->ouIdx = idx; + idx += dName->ouLen; + } + if (dName->emailLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14); + idx += 14; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->emailIdx], dName->emailLen); + dName->emailIdx = idx; + idx += dName->emailLen; + } + if (dName->uidLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/UID=", 5); + idx += 5; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->uidIdx], dName->uidLen); + dName->uidIdx = idx; + idx += dName->uidLen; + } + if (dName->serialLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/serialNumber=", 14); + idx += 14; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->serialIdx], dName->serialLen); + dName->serialIdx = idx; + idx += dName->serialLen; + } + dName->fullName[idx] = '\0'; + dName->fullNameLen = totalLen; + } + } + #endif /* OPENSSL_EXTRA */ + return 0; } @@ -1878,15 +2058,13 @@ static int GetDate(DecodedCert* cert, int dateType) int length; byte date[MAX_DATE_SIZE]; byte b; - -#ifdef CYASSL_CERT_GEN word32 startIdx = 0; + if (dateType == BEFORE) cert->beforeDate = &cert->source[cert->srcIdx]; else cert->afterDate = &cert->source[cert->srcIdx]; startIdx = cert->srcIdx; -#endif b = cert->source[cert->srcIdx++]; if (b != ASN_UTC_TIME && b != ASN_GENERALIZED_TIME) @@ -1901,12 +2079,10 @@ static int GetDate(DecodedCert* cert, int dateType) XMEMCPY(date, &cert->source[cert->srcIdx], length); cert->srcIdx += length; -#ifdef CYASSL_CERT_GEN if (dateType == BEFORE) cert->beforeDateLen = cert->srcIdx - startIdx; else cert->afterDateLen = cert->srcIdx - startIdx; -#endif if (!XVALIDATE_DATE(date, b, dateType)) { if (dateType == BEFORE) diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index 1e6d34cf4..70dbfbe09 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -223,7 +223,36 @@ struct DNS_entry { char* name; /* actual DNS name */ }; + +struct DecodedName { + char* fullName; + int fullNameLen; + int entryCount; + int cnIdx; + int cnLen; + int snIdx; + int snLen; + int cIdx; + int cLen; + int lIdx; + int lLen; + int stIdx; + int stLen; + int oIdx; + int oLen; + int ouIdx; + int ouLen; + int emailIdx; + int emailLen; + int uidIdx; + int uidLen; + int serialIdx; + int serialLen; +}; + + typedef struct DecodedCert DecodedCert; +typedef struct DecodedName DecodedName; typedef struct Signer Signer; @@ -236,6 +265,7 @@ struct DecodedCert { word32 sigLength; /* length of signature */ word32 signatureOID; /* sum of algorithm object id */ word32 keyOID; /* sum of key algo object id */ + int version; /* cert version, 1 or 3 */ DNS_entry* altNames; /* alt names list of dns entries */ byte subjectHash[SHA_SIZE]; /* hash of all Names */ byte issuerHash[SHA_SIZE]; /* hash of all Names */ @@ -267,7 +297,11 @@ struct DecodedCert { byte extAuthKeyId[SHA_SIZE]; /* Authority Key ID */ byte extAuthKeyIdSet; /* Set when the AKID was read from cert */ byte isCA; /* CA basic constraint true */ -#ifdef CYASSL_CERT_GEN + byte* beforeDate; + int beforeDateLen; + byte* afterDate; + int afterDateLen; +#if defined(CYASSL_CERT_GEN) /* easy access to subject info for other sign */ char* subjectSN; int subjectSNLen; @@ -283,11 +317,11 @@ struct DecodedCert { int subjectOULen; char* subjectEmail; int subjectEmailLen; - byte* beforeDate; - int beforeDateLen; - byte* afterDate; - int afterDateLen; #endif /* CYASSL_CERT_GEN */ +#ifdef OPENSSL_EXTRA + DecodedName issuerName; + DecodedName subjectName; +#endif /* OPENSSL_EXTRA */ #ifdef CYASSL_SEP int deviceTypeSz; byte* deviceType; @@ -298,6 +332,7 @@ struct DecodedCert { #endif /* CYASSL_SEP */ }; + #ifdef SHA_DIGEST_SIZE #define SIGNER_DIGEST_SIZE SHA_DIGEST_SIZE #else diff --git a/cyassl/internal.h b/cyassl/internal.h index 3a0ed9147..8fe14fe45 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1621,9 +1621,18 @@ typedef struct Arrays { #define ASN_NAME_MAX 256 #endif +#ifndef MAX_DATE_SZ +#define MAX_DATE_SZ 32 +#endif + struct CYASSL_X509_NAME { - char name[ASN_NAME_MAX]; + char *name; + char staticName[ASN_NAME_MAX]; + int dynamicName; int sz; +#ifdef OPENSSL_EXTRA + DecodedName fullName; +#endif /* OPENSSL_EXTRA */ }; #ifndef EXTERNAL_SERIAL_SIZE @@ -1635,6 +1644,7 @@ struct CYASSL_X509_NAME { #endif struct CYASSL_X509 { + int version; CYASSL_X509_NAME issuer; CYASSL_X509_NAME subject; int serialSz; @@ -1648,6 +1658,11 @@ struct CYASSL_X509 { int hwSerialNumSz; byte hwSerialNum[EXTERNAL_SERIAL_SIZE]; #endif + int notBeforeSz; + byte notBefore[MAX_DATE_SZ]; + int notAfterSz; + byte notAfter[MAX_DATE_SZ]; + buffer pubKey; buffer derCert; /* may need */ DNS_entry* altNames; /* alt names list */ DNS_entry* altNamesNext; /* hint for retrieval */ @@ -2025,6 +2040,8 @@ CYASSL_LOCAL int GrowInputBuffer(CYASSL* ssl, int size, int usedLength); CYASSL_LOCAL word32 LowResTimer(void); +CYASSL_LOCAL void InitX509Name(CYASSL_X509_NAME*, int); +CYASSL_LOCAL void FreeX509Name(CYASSL_X509_NAME* name); CYASSL_LOCAL void InitX509(CYASSL_X509*, int); CYASSL_LOCAL void FreeX509(CYASSL_X509*); #ifndef NO_CERTS diff --git a/cyassl/ssl.h b/cyassl/ssl.h index 340f3fa68..245cdebf4 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -95,6 +95,10 @@ typedef struct CYASSL_dynlock_value CYASSL_dynlock_value; typedef struct CYASSL_EVP_PKEY { int type; /* openssh dereference */ int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; + } pkey; } CYASSL_EVP_PKEY; typedef struct CYASSL_MD4_CTX { @@ -108,7 +112,8 @@ typedef struct CYASSL_COMP_METHOD { typedef struct CYASSL_X509_STORE { - int cache; /* stunnel dereference */ + int cache; /* stunnel dereference */ + CYASSL_CERT_MANAGER* cm; } CYASSL_X509_STORE; typedef struct CYASSL_ALERT { @@ -135,6 +140,7 @@ typedef struct CYASSL_X509_OBJECT { typedef struct CYASSL_X509_STORE_CTX { + CYASSL_X509_STORE* store; /* Store full of a CA cert chain */ CYASSL_X509* current_cert; /* stunnel dereference */ char* domain; /* subject CN domain name */ void* ex_data; /* external data, for fortress build */ @@ -407,6 +413,10 @@ CYASSL_API int CyaSSL_X509_STORE_CTX_get_error_depth(CYASSL_X509_STORE_CTX*); CYASSL_API char* CyaSSL_X509_NAME_oneline(CYASSL_X509_NAME*, char*, int); CYASSL_API CYASSL_X509_NAME* CyaSSL_X509_get_issuer_name(CYASSL_X509*); CYASSL_API CYASSL_X509_NAME* CyaSSL_X509_get_subject_name(CYASSL_X509*); +CYASSL_API int CyaSSL_X509_NAME_entry_count(CYASSL_X509_NAME*); +CYASSL_API int CyaSSL_X509_NAME_get_text_by_NID( + CYASSL_X509_NAME*, int, char*, int); +CYASSL_API int CyaSSL_X509_verify_cert(CYASSL_X509_STORE_CTX*); CYASSL_API const char* CyaSSL_X509_verify_cert_error_string(long); CYASSL_API int CyaSSL_X509_LOOKUP_add_dir(CYASSL_X509_LOOKUP*,const char*,long); @@ -418,10 +428,16 @@ CYASSL_API CYASSL_X509_LOOKUP_METHOD* CyaSSL_X509_LOOKUP_file(void); CYASSL_API CYASSL_X509_LOOKUP* CyaSSL_X509_STORE_add_lookup(CYASSL_X509_STORE*, CYASSL_X509_LOOKUP_METHOD*); CYASSL_API CYASSL_X509_STORE* CyaSSL_X509_STORE_new(void); +CYASSL_API void CyaSSL_X509_STORE_free(CYASSL_X509_STORE*); +CYASSL_API int CyaSSL_X509_STORE_add_cert( + CYASSL_X509_STORE*, CYASSL_X509*); +CYASSL_API int CyaSSL_X509_STORE_set_default_paths(CYASSL_X509_STORE*); CYASSL_API int CyaSSL_X509_STORE_get_by_subject(CYASSL_X509_STORE_CTX*, int, CYASSL_X509_NAME*, CYASSL_X509_OBJECT*); +CYASSL_API CYASSL_X509_STORE_CTX* CyaSSL_X509_STORE_CTX_new(void); CYASSL_API int CyaSSL_X509_STORE_CTX_init(CYASSL_X509_STORE_CTX*, CYASSL_X509_STORE*, CYASSL_X509*, STACK_OF(CYASSL_X509)*); +CYASSL_API void CyaSSL_X509_STORE_CTX_free(CYASSL_X509_STORE_CTX*); CYASSL_API void CyaSSL_X509_STORE_CTX_cleanup(CYASSL_X509_STORE_CTX*); CYASSL_API CYASSL_ASN1_TIME* CyaSSL_X509_CRL_get_lastUpdate(CYASSL_X509_CRL*); @@ -778,13 +794,21 @@ CYASSL_API const unsigned char* CyaSSL_get_sessionID(const CYASSL_SESSION* s); CYASSL_API int CyaSSL_X509_get_serial_number(CYASSL_X509*,unsigned char*,int*); CYASSL_API char* CyaSSL_X509_get_subjectCN(CYASSL_X509*); CYASSL_API const unsigned char* CyaSSL_X509_get_der(CYASSL_X509*, int*); +CYASSL_API const unsigned char* CyaSSL_X509_notBefore(CYASSL_X509*); +CYASSL_API const unsigned char* CyaSSL_X509_notAfter(CYASSL_X509*); +CYASSL_API int CyaSSL_X509_version(CYASSL_X509*); +CYASSL_API CYASSL_API int CyaSSL_cmp_peer_cert_to_file(CYASSL*, const char*); CYASSL_API char* CyaSSL_X509_get_next_altname(CYASSL_X509*); -CYASSL_API -CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format); +CYASSL_API CYASSL_X509* + CyaSSL_X509_d2i(CYASSL_X509** x509, const unsigned char* in, int len); +CYASSL_API CYASSL_X509* + CyaSSL_X509_d2i_fp(CYASSL_X509** x509, FILE* file); +CYASSL_API CYASSL_X509* + CyaSSL_X509_load_certificate_file(const char* fname, int format); #ifdef CYASSL_SEP CYASSL_API unsigned char* diff --git a/src/internal.c b/src/internal.c index af5a97978..94d50d7fa 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1231,9 +1231,41 @@ void InitSuites(Suites* suites, ProtocolVersion pv, byte haveRSA, byte havePSK, #ifndef NO_CERTS + +void InitX509Name(CYASSL_X509_NAME* name, int dynamicFlag) +{ + (void)dynamicFlag; + + if (name != NULL) { + name->name = name->staticName; + name->dynamicName = 0; +#ifdef OPENSSL_EXTRA + XMEMSET(&name->fullName, 0, sizeof(DecodedName)); +#endif /* OPENSSL_EXTRA */ + } +} + + +void FreeX509Name(CYASSL_X509_NAME* name) +{ + if (name != NULL) { + if (name->dynamicName) + XFREE(name->name, NULL, DYNAMIC_TYPE_SUBJECT_CN); +#ifdef OPENSSL_EXTRA + if (name->fullName.fullName != NULL) + XFREE(name->fullName.fullName, NULL, DYNAMIC_TYPE_X509); +#endif /* OPENSSL_EXTRA */ + } +} + + /* Initialize CyaSSL X509 type */ void InitX509(CYASSL_X509* x509, int dynamicFlag) { + InitX509Name(&x509->issuer, 0); + InitX509Name(&x509->subject, 0); + x509->version = 0; + x509->pubKey.buffer = NULL; x509->derCert.buffer = NULL; x509->altNames = NULL; x509->altNamesNext = NULL; @@ -1247,7 +1279,11 @@ void FreeX509(CYASSL_X509* x509) if (x509 == NULL) return; - XFREE(x509->derCert.buffer, NULL, DYNAMIC_TYPE_CERT); + FreeX509Name(&x509->issuer); + FreeX509Name(&x509->subject); + if (x509->pubKey.buffer) + XFREE(x509->pubKey.buffer, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(x509->derCert.buffer, NULL, DYNAMIC_TYPE_SUBJECT_CN); if (x509->altNames) FreeAltNames(x509->altNames, NULL); if (x509->dynamicMemory) @@ -2998,13 +3034,37 @@ int CopyDecodedToX509(CYASSL_X509* x509, DecodedCert* dCert) if (x509 == NULL || dCert == NULL) return BAD_FUNC_ARG; + x509->version = dCert->version + 1; + XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX); x509->issuer.name[ASN_NAME_MAX - 1] = '\0'; x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1; +#ifdef OPENSSL_EXTRA + if (dCert->issuerName.fullName != NULL) { + XMEMCPY(&x509->issuer.fullName, + &dCert->issuerName, sizeof(DecodedName)); + x509->issuer.fullName.fullName = (char*)XMALLOC( + dCert->issuerName.fullNameLen, NULL, DYNAMIC_TYPE_X509); + if (x509->issuer.fullName.fullName != NULL) + XMEMCPY(x509->issuer.fullName.fullName, + dCert->issuerName.fullName, dCert->issuerName.fullNameLen); + } +#endif /* OPENSSL_EXTRA */ XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX); x509->subject.name[ASN_NAME_MAX - 1] = '\0'; x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1; +#ifdef OPENSSL_EXTRA + if (dCert->subjectName.fullName != NULL) { + XMEMCPY(&x509->subject.fullName, + &dCert->subjectName, sizeof(DecodedName)); + x509->subject.fullName.fullName = (char*)XMALLOC( + dCert->subjectName.fullNameLen, NULL, DYNAMIC_TYPE_X509); + if (x509->subject.fullName.fullName != NULL) + XMEMCPY(x509->subject.fullName.fullName, + dCert->subjectName.fullName, dCert->subjectName.fullNameLen); + } +#endif /* OPENSSL_EXTRA */ XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); x509->serialSz = dCert->serialSz; @@ -3040,6 +3100,33 @@ int CopyDecodedToX509(CYASSL_X509* x509, DecodedCert* dCert) x509->hwSerialNumSz = 0; } #endif /* CYASSL_SEP */ + { + int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ); + if (minSz != 0) { + x509->notBeforeSz = minSz; + XMEMCPY(x509->notBefore, dCert->beforeDate, minSz); + } + else + x509->notBeforeSz = 0; + minSz = min(dCert->afterDateLen, MAX_DATE_SZ); + if (minSz != 0) { + x509->notAfterSz = minSz; + XMEMCPY(x509->notAfter, dCert->afterDate, minSz); + } + else + x509->notAfterSz = 0; + } + + if (dCert->publicKey != NULL && dCert->pubKeySize != 0) { + x509->pubKey.buffer = (byte*)XMALLOC( + dCert->pubKeySize, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (x509->pubKey.buffer != NULL) { + x509->pubKey.length = dCert->pubKeySize; + XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize); + } + else + ret = MEMORY_E; + } /* store cert for potential retrieval */ x509->derCert.buffer = (byte*)XMALLOC(dCert->maxIdx, NULL, diff --git a/src/ssl.c b/src/ssl.c index 2ee2c8e83..cc21ba2a7 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5613,7 +5613,8 @@ int CyaSSL_set_compression(CYASSL* ssl) int CyaSSL_X509_STORE_CTX_get_error(CYASSL_X509_STORE_CTX* ctx) { - (void)ctx; + if (ctx != NULL) + return ctx->error; return 0; } @@ -7066,6 +7067,76 @@ int CyaSSL_set_compression(CYASSL* ssl) } + int CyaSSL_X509_NAME_entry_count(CYASSL_X509_NAME* name) + { + int count = 0; + + CYASSL_ENTER("CyaSSL_X509_NAME_entry_count"); + + if (name != NULL) + count = name->fullName.entryCount; + + CYASSL_LEAVE("CyaSSL_X509_NAME_entry_count", count); + return count; + } + + + int CyaSSL_X509_NAME_get_text_by_NID(CYASSL_X509_NAME* name, + int nid, char* buf, int len) + { + char *text = NULL; + int textSz = 0; + + CYASSL_ENTER("CyaSSL_X509_NAME_get_text_by_NID"); + + switch (nid) { + case ASN_COMMON_NAME: + text = name->fullName.fullName + name->fullName.cnIdx; + textSz = name->fullName.cnLen; + break; + case ASN_SUR_NAME: + text = name->fullName.fullName + name->fullName.snIdx; + textSz = name->fullName.snLen; + break; + case ASN_SERIAL_NUMBER: + text = name->fullName.fullName + name->fullName.serialIdx; + textSz = name->fullName.serialLen; + break; + case ASN_COUNTRY_NAME: + text = name->fullName.fullName + name->fullName.cIdx; + textSz = name->fullName.cLen; + break; + case ASN_LOCALITY_NAME: + text = name->fullName.fullName + name->fullName.lIdx; + textSz = name->fullName.lLen; + break; + case ASN_STATE_NAME: + text = name->fullName.fullName + name->fullName.stIdx; + textSz = name->fullName.stLen; + break; + case ASN_ORG_NAME: + text = name->fullName.fullName + name->fullName.oIdx; + textSz = name->fullName.oLen; + break; + case ASN_ORGUNIT_NAME: + text = name->fullName.fullName + name->fullName.ouIdx; + textSz = name->fullName.ouLen; + break; + default: + break; + } + + if (buf != NULL) { + textSz = min(textSz, len); + XMEMCPY(buf, text, textSz); + buf[textSz] = '\0'; + } + + CYASSL_LEAVE("CyaSSL_X509_NAME_get_text_by_NID", textSz); + return textSz; + } + + /* write X509 serial number in unsigned binary to buffer buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases return SSL_SUCCESS on success */ @@ -7093,6 +7164,40 @@ int CyaSSL_set_compression(CYASSL* ssl) return x509->derCert.buffer; } + + int CyaSSL_X509_version(CYASSL_X509* x509) + { + CYASSL_ENTER("CyaSSL_X509_version"); + + if (x509 == NULL) + return 0; + + return x509->version; + } + + + const byte* CyaSSL_X509_notBefore(CYASSL_X509* x509) + { + CYASSL_ENTER("CyaSSL_X509_notBefore"); + + if (x509 == NULL) + return NULL; + + return x509->notBefore; + } + + + const byte* CyaSSL_X509_notAfter(CYASSL_X509* x509) + { + CYASSL_ENTER("CyaSSL_X509_notAfter"); + + if (x509 == NULL) + return NULL; + + return x509->notAfter; + } + + #ifdef CYASSL_SEP /* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will @@ -7169,6 +7274,66 @@ byte* CyaSSL_X509_get_hw_serial_number(CYASSL_X509* x509,byte* in,int* inOutSz) #endif /* CYASSL_SEP */ +CYASSL_X509* CyaSSL_X509_d2i(CYASSL_X509** x509, const byte* in, int len) +{ + CYASSL_X509 *newX509 = NULL; + + CYASSL_ENTER("CyaSSL_X509_d2i"); + + if (in != NULL && len != 0) { + DecodedCert cert; + + InitDecodedCert(&cert, (byte*)in, len, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, 0, NULL) == 0) { + newX509 = (CYASSL_X509*)XMALLOC(sizeof(CYASSL_X509), + NULL, DYNAMIC_TYPE_X509); + if (newX509 != NULL) { + InitX509(newX509, 1); + if (CopyDecodedToX509(newX509, &cert) != 0) { + XFREE(newX509, NULL, DYNAMIC_TYPE_X509); + newX509 = NULL; + } + } + } + FreeDecodedCert(&cert); + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} + + +CYASSL_X509* CyaSSL_X509_d2i_fp(CYASSL_X509** x509, XFILE file) +{ + CYASSL_X509* newX509 = NULL; + + CYASSL_ENTER("CyaSSL_X509_d2i_fp"); + + if (file != XBADFILE) { + byte* fileBuffer = NULL; + long sz = 0; + + XFSEEK(file, 0, XSEEK_END); + sz = XFTELL(file); + XREWIND(file); + + fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer != NULL) { + if ((int)XFREAD(fileBuffer, sz, 1, file) > 0) { + newX509 = CyaSSL_X509_d2i(NULL, fileBuffer, (int)sz); + } + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + } + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} + CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format) { byte staticBuffer[FILE_BUFFER_SIZE]; @@ -7965,9 +8130,61 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format) } + int CyaSSL_X509_STORE_add_cert(CYASSL_X509_STORE* store, CYASSL_X509* x509) + { + int result = SSL_FATAL_ERROR; + + CYASSL_ENTER("CyaSSL_X509_STORE_add_cert"); + if (store != NULL && store->cm != NULL && x509 != NULL) { + buffer derCert; + derCert.buffer = (byte*)XMALLOC(x509->derCert.length, + NULL, DYNAMIC_TYPE_CERT); + if (derCert.buffer != NULL) { + derCert.length = x509->derCert.length; + // AddCA() frees the buffer. + XMEMCPY(derCert.buffer, + x509->derCert.buffer, x509->derCert.length); + result = AddCA(store->cm, derCert, CYASSL_USER_CA, 1); + if (result != SSL_SUCCESS) result = SSL_FATAL_ERROR; + } + } + + CYASSL_LEAVE("CyaSSL_X509_STORE_add_cert", result); + return result; + } + + CYASSL_X509_STORE* CyaSSL_X509_STORE_new(void) { - return 0; + CYASSL_X509_STORE* store = NULL; + + store = (CYASSL_X509_STORE*)XMALLOC(sizeof(CYASSL_X509_STORE), NULL, 0); + if (store != NULL) { + store->cm = CyaSSL_CertManagerNew(); + if (store->cm == NULL) { + XFREE(store, NULL, 0); + store = NULL; + } + } + + return store; + } + + + void CyaSSL_X509_STORE_free(CYASSL_X509_STORE* store) + { + if (store != NULL) { + if (store->cm != NULL) + CyaSSL_CertManagerFree(store->cm); + XFREE(store, NULL, 0); + } + } + + + int CyaSSL_X509_STORE_set_default_paths(CYASSL_X509_STORE* store) + { + (void)store; + return SSL_SUCCESS; } @@ -7982,14 +8199,46 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format) } + CYASSL_X509_STORE_CTX* CyaSSL_X509_STORE_CTX_new(void) + { + CYASSL_X509_STORE_CTX* ctx = (CYASSL_X509_STORE_CTX*)XMALLOC( + sizeof(CYASSL_X509_STORE_CTX), NULL, 0); + + if (ctx != NULL) + CyaSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL); + + return ctx; + } + + int CyaSSL_X509_STORE_CTX_init(CYASSL_X509_STORE_CTX* ctx, CYASSL_X509_STORE* store, CYASSL_X509* x509, STACK_OF(CYASSL_X509)* sk) { - (void)ctx; - (void)store; - (void)x509; (void)sk; - return 0; + if (ctx != NULL) { + ctx->store = store; + ctx->current_cert = x509; + ctx->domain = NULL; + ctx->ex_data = NULL; + ctx->userCtx = NULL; + ctx->error = 0; + ctx->error_depth = 0; + ctx->discardSessionCerts = 0; + return SSL_SUCCESS; + } + return SSL_FATAL_ERROR; + } + + + void CyaSSL_X509_STORE_CTX_free(CYASSL_X509_STORE_CTX* ctx) + { + if (ctx != NULL) { + if (ctx->store != NULL) + CyaSSL_X509_STORE_free(ctx->store); + if (ctx->current_cert != NULL) + CyaSSL_FreeX509(ctx->current_cert); + XFREE(ctx, NULL, 0); + } } @@ -7999,6 +8248,18 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format) } + int CyaSSL_X509_verify_cert(CYASSL_X509_STORE_CTX* ctx) + { + if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL + && ctx->current_cert != NULL) { + return CyaSSL_CertManagerVerifyBuffer(ctx->store->cm, + ctx->current_cert->derCert.buffer, + ctx->current_cert->derCert.length, + SSL_FILETYPE_ASN1); + } + return SSL_FATAL_ERROR; + } + CYASSL_ASN1_TIME* CyaSSL_X509_CRL_get_lastUpdate(CYASSL_X509_CRL* crl) { @@ -8017,8 +8278,25 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format) CYASSL_EVP_PKEY* CyaSSL_X509_get_pubkey(CYASSL_X509* x509) { - (void)x509; - return 0; + CYASSL_EVP_PKEY* key = NULL; + if (x509 != NULL) { + key = (CYASSL_EVP_PKEY*)XMALLOC( + sizeof(CYASSL_EVP_PKEY), NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (key != NULL) { + key->type = 0; + key->save_type = 0; + key->pkey.ptr = (char*)XMALLOC( + x509->pubKey.length, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (key->pkey.ptr == NULL) { + XFREE(key, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + XMEMCPY(key->pkey.ptr, + x509->pubKey.buffer, x509->pubKey.length); + key->pkey_sz = x509->pubKey.length; + } + } + return key; } @@ -8045,7 +8323,11 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format) void CyaSSL_EVP_PKEY_free(CYASSL_EVP_PKEY* key) { - (void)key; + if (key != NULL) { + if (key->pkey.ptr != NULL) + XFREE(key->pkey.ptr, NULL, 0); + XFREE(key, NULL, 0); + } }