*
* Copyright (C) 2006-2023 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
* WOLFSSL_SYS_CA_CERTS
* Enables ability to load system CA certs from the OS via
* wolfSSL_CTX_load_system_CA_certs.
*/
#ifdef WOLFSSL_SYS_CA_CERTS
#ifdef _WIN32
#include <windows.h>
#include <wincrypt.h>
* linking with crypt32 is handled in configure.ac */
#if !defined(__MINGW32__) && !defined(__MINGW64__)
#pragma comment(lib, "crypt32")
#endif
#endif
#if defined(__APPLE__) && defined(HAVE_SECURITY_SECTRUSTSETTINGS_H)
#include <Security/SecTrustSettings.h>
#endif
#endif
#if !defined(WOLFSSL_SSL_LOAD_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
#warning ssl_load.c does not need to be compiled separately from ssl.c
#endif
#else
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
#define CTX_HAVE_PSK(ctx) (ctx)->havePSK
#define SSL_HAVE_PSK(ssl) (ssl)->options.havePSK
#else
#define CTX_HAVE_PSK(ctx) 0
#define SSL_HAVE_PSK(ssl) 0
#endif
#ifdef NO_RSA
#define WOLFSSL_HAVE_RSA 0
#else
#define WOLFSSL_HAVE_RSA 1
#endif
#ifndef NO_CERTS
#define SSL_KEY_SZ(ssl) (ssl)->buffers.keySz
#else
#define SSL_KEY_SZ(ssl) 0
#endif
#ifdef HAVE_ANON
#define CTX_USE_ANON(ctx) (ctx)->useAnon
#else
#define CTX_USE_ANON(ctx) 0
#endif
#ifdef HAVE_PK_CALLBACKS
#define WOLFSSL_IS_PRIV_PK_SET(ctx, ssl) \
wolfSSL_CTX_IsPrivatePkSet(((ssl) == NULL) ? (ctx) : (ssl)->ctx)
#else
#define WOLFSSL_IS_PRIV_PK_SET(ctx, ssl) 0
#endif
#define WOLFSSL_HEAP(ctx, ssl) \
(((ctx) != NULL) ? (ctx)->heap : (((ssl) != NULL) ? (ssl)->heap : NULL))
#ifndef NO_CERTS
*
* @param [in] buff Buffer containing data.
* @param [in] len Length of data in buffer.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @param [in] type Type of data:
* CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE,
* PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
* @param [in, out] info Info for encryption.
* @param [in] heap Dynamic memory allocation hint.
* @param [out] der Holds DER encoded data.
* @param [out] algId Algorithm identifier for private keys.
* @return 0 on success.
* @return NOT_COMPILED_IN when format is PEM and PEM not supported.
* @return ASN_PARSE_E when format is ASN.1 and invalid DER encoding.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int DataToDerBuffer(const unsigned char* buff, word32 len, int format,
int type, EncryptedInfo* info, void* heap, DerBuffer** der, int* algId)
{
int ret;
info->consumed = 0;
if (format == WOLFSSL_FILETYPE_PEM) {
#ifdef WOLFSSL_PEM_TO_DER
ret = PemToDer(buff, len, type, der, heap, info, algId);
if (ret != 0) {
FreeDer(der);
}
#else
ret = NOT_COMPILED_IN;
#endif
}
else {
int length;
word32 inOutIdx = 0;
if ((info->consumed = wolfssl_der_length(buff, (int)len)) > 0) {
ret = 0;
}
* TODO: is this really needed? */
else if ((type == PRIVATEKEY_TYPE) &&
(GetOctetString(buff, &inOutIdx, &length, len) >= 0)) {
info->consumed = length + inOutIdx;
ret = 0;
}
else {
ret = ASN_PARSE_E;
}
if (info->consumed > (int)len) {
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = AllocCopyDer(der, buff, (word32)info->consumed, type, heap);
}
}
return ret;
}
*
* Puts the 3-byte length before certificate data as required for TLS.
* CA certificates are added to the certificate manager.
*
* @param [in] cm Certificate manager.
* @param [in, out] pDer DER encoded data.
* @param [in] type Type of data. Valid values:
* CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE.
* @param [in] verify How to verify certificate.
* @param [out] chainBuffer Buffer to hold chain of certificates.
* @param [in, out] pIdx On in, current index into chainBuffer.
* On out, index after certificate added.
* @param [in] bufferSz Size of buffer in bytes.
* @return 0 on success.
* @return BUFFER_E if chain buffer not big enough to hold certificate.
*/
static int ProcessUserCert(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer,
int type, int verify, byte* chainBuffer, word32* pIdx, word32 bufferSz)
{
int ret = 0;
word32 idx = *pIdx;
DerBuffer* der = *pDer;
if ((ret == 0) && ((idx + der->length + CERT_HEADER_SZ) > bufferSz)) {
WOLFSSL_MSG(" Cert Chain bigger than buffer. "
"Consider increasing MAX_CHAIN_DEPTH");
ret = BUFFER_E;
}
if (ret == 0) {
c32to24(der->length, &chainBuffer[idx]);
idx += CERT_HEADER_SZ;
XMEMCPY(&chainBuffer[idx], der->buffer, der->length);
idx += der->length;
if (type == CA_TYPE) {
ret = AddCA(cm, pDer, WOLFSSL_USER_CA, verify);
if (ret == 1) {
ret = 0;
}
}
}
*pIdx = idx;
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] chainBuffer Buffer containing chain of certificates.
* @param [in] len Length, in bytes, of data in buffer.
* @param [in] cnt Number of certificates in chain.
* @param [in] type Type of data. Valid values:
* CERT_TYPE, CA_TYPE or CHAIN_CERT_TYPE.
* @param [in] heap Dynamic memory allocation hint.
* @return 0 on success.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int ProcessUserChainRetain(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const byte* chainBuffer, word32 len, int cnt, int type, void* heap)
{
int ret = 0;
(void)cnt;
if (ssl != NULL) {
if (ssl->buffers.weOwnCertChain) {
FreeDer(&ssl->buffers.certChain);
}
ret = AllocCopyDer(&ssl->buffers.certChain, chainBuffer, len, type,
heap);
ssl->buffers.weOwnCertChain = (ret == 0);
#ifdef WOLFSSL_TLS13
ssl->buffers.certChainCnt = cnt;
#endif
}
else if (ctx != NULL) {
FreeDer(&ctx->certChain);
ret = AllocCopyDer(&ctx->certChain, chainBuffer, len, type, heap);
#ifdef WOLFSSL_TLS13
ctx->certChainCnt = cnt;
#endif
}
return ret;
}
*
* If not a certificate type then data is ignored.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] buff Buffer holding certificates.
* @param [in] sz Length of data in buffer.
* @param [in] format Format of the certificate:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1
* @param [in] type Type of certificate:
* CA_TYPE, CERT_TYPE or CHAIN_CERT_TYPE
* @param [out] used Number of bytes from buff used.
* @param [in, out] info Encryption information.
* @param [in] verify How to verify certificate.
* @return 0 on success.
* @return BAD_FUNC_ARG when type is CA_TYPE and ctx is NULL.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int ProcessUserChain(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const unsigned char* buff, long sz, int format, int type, long* used,
EncryptedInfo* info, int verify)
{
int ret = 0;
void* heap = WOLFSSL_HEAP(ctx, ssl);
WOLFSSL_ENTER("ProcessUserChain");
if ((type == CA_TYPE) && (ctx == NULL)) {
WOLFSSL_MSG("Need context for CA load");
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (type != CERT_TYPE) && (type != CHAIN_CERT_TYPE) &&
(type != CA_TYPE)) {
WOLFSSL_MSG("File type not a certificate");
}
else if ((ret == 0) && (info->consumed >= sz)) {
WOLFSSL_MSG("Already consumed data");
}
else if (ret == 0) {
#ifndef WOLFSSL_SMALL_STACK
byte stackBuffer[FILE_BUFFER_SIZE];
#endif
StaticBuffer chain;
long consumed = info->consumed;
word32 idx = 0;
int gotOne = 0;
int cnt = 0;
long maxSz = (sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH);
#ifdef WOLFSSL_SMALL_STACK
static_buffer_init(&chain);
#else
static_buffer_init(&chain, stackBuffer, FILE_BUFFER_SIZE);
#endif
ret = static_buffer_set_size(&chain, (word32)maxSz, heap,
DYNAMIC_TYPE_FILE);
WOLFSSL_MSG("Processing Cert Chain");
while ((ret == 0) && (consumed < sz)) {
DerBuffer* part = NULL;
ret = DataToDerBuffer(buff + consumed, (word32)(sz - consumed),
format, type, info, heap, &part, NULL);
if (ret == 0) {
ret = ProcessUserCert(ctx->cm, &part, type, verify,
chain.buffer, &idx, (word32)maxSz);
}
if ((ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) && gotOne) {
WOLFSSL_MSG("We got one good cert, so stuff at end ok");
ret = 0;
break;
}
FreeDer(&part);
if (ret == 0) {
consumed += info->consumed;
WOLFSSL_MSG(" Consumed another Cert in Chain");
gotOne |= (type != CA_TYPE);
cnt++;
}
}
if (used != NULL) {
*used = consumed;
}
if ((ret == 0) && (idx > 0)) {
ret = ProcessUserChainRetain(ctx, ssl, chain.buffer, idx, cnt, type,
heap);
}
static_buffer_free(&chain, heap, DYNAMIC_TYPE_FILE);
}
WOLFSSL_LEAVE("ProcessUserChain", ret);
return ret;
}
#ifndef NO_RSA
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION > 2))
*
* Checks size meets minimum RSA key size.
* This implementation uses less dynamic memory.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not an RSA key and format unknown.
* @return RSA_KEY_SIZE_E when key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, int devId, byte* keyType, int* keySize)
{
int ret;
word32 idx;
int keySz = 0;
(void)devId;
idx = 0;
ret = wc_RsaPrivateKeyValidate(der->buffer, &idx, &keySz, der->length);
#ifdef WOLF_PRIVATE_KEY_ID
if ((ret != 0) && ((devId != INVALID_DEVID) ||
WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
word32 nSz;
idx = 0;
ret = wc_RsaPublicKeyDecode_ex(der->buffer, &idx, der->length, NULL,
&nSz, NULL, NULL);
if (ret == 0) {
keySz = (int)nSz;
}
}
#endif
if (ret == 0) {
int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz;
*keyFormat = RSAk;
*keyType = rsa_sa_algo;
*keySize = keySz;
if (keySz < minRsaSz) {
WOLFSSL_MSG("Private Key size too small");
ret = RSA_KEY_SIZE_E;
}
if ((ssl != NULL) && (ssl->options.side == WOLFSSL_SERVER_END)) {
ssl->options.haveStaticECC = 0;
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not an RSA key");
ret = 0;
}
return ret;
}
#else
*
* Checks size meets minimum RSA key size.
* This implementation uses more dynamic memory but supports older FIPS.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not an RSA key and format unknown.
* @return RSA_KEY_SIZE_E when key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeRsa(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
int* keySize)
{
int ret;
word32 idx;
#ifdef WOLFSSL_SMALL_STACK
RsaKey* key;
#else
RsaKey key[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA);
if (key == NULL)
return MEMORY_E;
#endif
ret = wc_InitRsaKey_ex(key, heap, devId);
if (ret == 0) {
idx = 0;
ret = wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length);
#ifdef WOLF_PRIVATE_KEY_ID
*/
if ((ret != 0) && ((devId != INVALID_DEVID) ||
WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
* callback. */
idx = 0;
ret = wc_RsaPublicKeyDecode(der->buffer, &idx, key, der->length);
}
#endif
if (ret == 0) {
int minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz;
int keySz = wc_RsaEncryptSize((RsaKey*)key);
*keyFormat = RSAk;
*keyType = rsa_sa_algo;
*keySize = keySz;
if (keySz < minRsaSz) {
WOLFSSL_MSG("Private Key size too small");
ret = RSA_KEY_SIZE_E;
}
if ((ssl != NULL) && (ssl->options.side == WOLFSSL_SERVER_END)) {
ssl->options.haveStaticECC = 0;
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not an RSA key");
ret = 0;
}
wc_FreeRsaKey(key);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(key, heap, DYNAMIC_TYPE_RSA);
#endif
return ret;
}
#endif
#endif
#ifdef HAVE_ECC
*
* Checks size meets minimum ECC key size.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not an ECC key and format unknown.
* @return ECC_KEY_SIZE_E when ECC key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeEcc(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
int* keySize)
{
int ret = 0;
word32 idx;
#ifdef WOLFSSL_SMALL_STACK
ecc_key* key;
#else
ecc_key key[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC);
if (key == NULL)
return MEMORY_E;
#endif
if (wc_ecc_init_ex(key, heap, devId) == 0) {
idx = 0;
ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length);
#ifdef WOLF_PRIVATE_KEY_ID
*/
if ((ret != 0) && ((devId != INVALID_DEVID) ||
WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
idx = 0;
ret = wc_EccPublicKeyDecode(der->buffer, &idx, key, der->length);
}
#endif
#ifdef WOLFSSL_SM2
if (*keyFormat == SM2k) {
ret = wc_ecc_set_curve(key, WOLFSSL_SM2_KEY_BITS / 8,
ECC_SM2P256V1);
}
#endif
if (ret == 0) {
int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
int keySz = wc_ecc_size(key);
*keyFormat = ECDSAk;
#ifdef WOLFSSL_SM2
if (key->dp->id == ECC_SM2P256V1) {
*keyType = sm2_sa_algo;
}
else
#endif
{
*keyType = ecc_dsa_sa_algo;
}
*keySize = keySz;
if (keySz < minKeySz) {
WOLFSSL_MSG("ECC private key too small");
ret = ECC_KEY_SIZE_E;
}
if (ssl) {
ssl->options.haveStaticECC = 1;
}
else {
ctx->haveStaticECC = 1;
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not an ECC key");
ret = 0;
}
wc_ecc_free(key);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(key, heap, DYNAMIC_TYPE_ECC);
#endif
return ret;
}
#endif
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
*
* Checks size meets minimum ECC key size.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not an Ed25519 key and format unknown.
* @return ECC_KEY_SIZE_E when key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeEd25519(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
int* keySize)
{
int ret;
word32 idx;
#ifdef WOLFSSL_SMALL_STACK
ed25519_key* key;
#else
ed25519_key key[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
DYNAMIC_TYPE_ED25519);
if (key == NULL)
return MEMORY_E;
#endif
ret = wc_ed25519_init_ex(key, heap, devId);
if (ret == 0) {
idx = 0;
ret = wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key, der->length);
#ifdef WOLF_PRIVATE_KEY_ID
*/
if ((ret != 0) && ((devId != INVALID_DEVID) ||
WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
idx = 0;
ret = wc_Ed25519PublicKeyDecode(der->buffer, &idx, key,
der->length);
}
#endif
if (ret == 0) {
int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
*keyFormat = ED25519k;
*keyType = ed25519_sa_algo;
*keySize = ED25519_KEY_SIZE;
if (ED25519_KEY_SIZE < minKeySz) {
WOLFSSL_MSG("ED25519 private key too small");
ret = ECC_KEY_SIZE_E;
}
if (ssl != NULL) {
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && !defined(NO_ED25519_CLIENT_AUTH)
* hash used in EdDSA_Update for signing */
ssl->options.cacheMessages = 1;
#endif
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not an Ed25519 key");
ret = 0;
}
wc_ed25519_free(key);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(key, heap, DYNAMIC_TYPE_ED25519);
#endif
return ret;
}
#endif
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
*
* Checks size meets minimum ECC key size.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not an Ed448 key and format unknown.
* @return ECC_KEY_SIZE_E when key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeEd448(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, int devId, byte* keyType,
int* keySize)
{
int ret;
word32 idx;
#ifdef WOLFSSL_SMALL_STACK
ed448_key* key = NULL;
#else
ed448_key key[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
key = (ed448_key*)XMALLOC(sizeof(ed448_key), heap, DYNAMIC_TYPE_ED448);
if (key == NULL)
return MEMORY_E;
#endif
ret = wc_ed448_init_ex(key, heap, devId);
if (ret == 0) {
idx = 0;
ret = wc_Ed448PrivateKeyDecode(der->buffer, &idx, key, der->length);
#ifdef WOLF_PRIVATE_KEY_ID
*/
if ((ret != 0) && ((devId != INVALID_DEVID) ||
WOLFSSL_IS_PRIV_PK_SET(ctx, ssl))) {
idx = 0;
ret = wc_Ed448PublicKeyDecode(der->buffer, &idx, key, der->length);
}
#endif
if (ret == 0) {
int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz;
*keyFormat = ED448k;
*keyType = ed448_sa_algo;
*keySize = ED448_KEY_SIZE;
if (ED448_KEY_SIZE < minKeySz) {
WOLFSSL_MSG("ED448 private key too small");
ret = ECC_KEY_SIZE_E;
}
if (ssl != NULL) {
* hash used in EdDSA_Update for signing */
ssl->options.cacheMessages = 1;
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not an Ed448 key");
ret = 0;
}
wc_ed448_free(key);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(key, heap, DYNAMIC_TYPE_ED448);
#endif
return ret;
}
#endif
#if defined(HAVE_FALCON)
*
* Checks size meets minimum Falcon key size.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not an Falcon key and format unknown.
* @return FALCON_KEY_SIZE_E when key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeFalcon(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize)
{
int ret;
falcon_key* key;
key = (falcon_key*)XMALLOC(sizeof(falcon_key), heap, DYNAMIC_TYPE_FALCON);
if (key == NULL) {
return MEMORY_E;
}
ret = wc_falcon_init(key);
if (ret == 0) {
if (*keyFormat == FALCON_LEVEL1k) {
ret = wc_falcon_set_level(key, 1);
}
else if (*keyFormat == FALCON_LEVEL5k) {
ret = wc_falcon_set_level(key, 5);
}
else {
* graceful here. */
* compare with DER length. */
wc_falcon_free(key);
ret = ALGO_ID_E;
}
}
if (ret == 0) {
ret = wc_falcon_import_private_only(der->buffer, der->length, key);
if (ret == 0) {
*/
int minKeySz = ssl ? ssl->options.minFalconKeySz :
ctx->minFalconKeySz;
if (*keyFormat == FALCON_LEVEL1k) {
*keyType = falcon_level1_sa_algo;
*keySize = FALCON_LEVEL1_KEY_SIZE;
}
else {
*keyType = falcon_level5_sa_algo;
*keySize = FALCON_LEVEL5_KEY_SIZE;
}
if (*keySize < minKeySz) {
WOLFSSL_MSG("Falcon private key too small");
ret = FALCON_KEY_SIZE_E;
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not a Falcon key");
ret = 0;
}
wc_falcon_free(key);
}
XFREE(key, heap, DYNAMIC_TYPE_FALCON);
return ret;
}
#endif
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \
!defined(WOLFSSL_DILITHIUM_NO_ASN1)
*
* Checks size meets minimum Falcon key size.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] devId Device identifier.
* @param [out] keyType Type of key.
* @param [out] keySize Size of key.
* @return 0 on success or not a Dilithium key and format unknown.
* @return DILITHIUM_KEY_SIZE_E when key size doesn't meet minimum required.
*/
static int ProcessBufferTryDecodeDilithium(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, byte* keyType, int* keySize)
{
int ret;
word32 idx;
dilithium_key* key;
key = (dilithium_key*)XMALLOC(sizeof(dilithium_key), heap,
DYNAMIC_TYPE_DILITHIUM);
if (key == NULL) {
return MEMORY_E;
}
ret = wc_dilithium_init(key);
if (ret == 0) {
if (*keyFormat == DILITHIUM_LEVEL2k) {
ret = wc_dilithium_set_level(key, 2);
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
ret = wc_dilithium_set_level(key, 3);
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
ret = wc_dilithium_set_level(key, 5);
}
else {
* graceful here. */
* compare with DER length. */
wc_dilithium_free(key);
ret = ALGO_ID_E;
}
}
if (ret == 0) {
idx = 0;
ret = wc_Dilithium_PrivateKeyDecode(der->buffer, &idx, key, der->length);
if (ret == 0) {
* object. */
int minKeySz = ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz;
if (*keyFormat == DILITHIUM_LEVEL2k) {
*keyType = dilithium_level2_sa_algo;
*keySize = DILITHIUM_LEVEL2_KEY_SIZE;
}
else if (*keyFormat == DILITHIUM_LEVEL3k) {
*keyType = dilithium_level3_sa_algo;
*keySize = DILITHIUM_LEVEL3_KEY_SIZE;
}
else if (*keyFormat == DILITHIUM_LEVEL5k) {
*keyType = dilithium_level5_sa_algo;
*keySize = DILITHIUM_LEVEL5_KEY_SIZE;
}
if (*keySize < minKeySz) {
WOLFSSL_MSG("Dilithium private key too small");
ret = DILITHIUM_KEY_SIZE_E;
}
}
else if (*keyFormat == 0) {
WOLFSSL_MSG("Not a Dilithium key");
ret = 0;
}
wc_dilithium_free(key);
}
XFREE(key, heap, DYNAMIC_TYPE_DILITHIUM);
return ret;
}
#endif
*
* Checks size meets minimum for key type.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in, out] keyFormat On in, expected format. 0 means unknown.
* @param [in] heap Dynamic memory allocation hint.
* @param [out] type Type of key:
* PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
* @return 0 on success.
* @return BAD_FUNC_ARG when der or keyFormat is NULL.
* @return BAD_FUNC_ARG when ctx and ssl are NULL.
* @return WOLFSSL_BAD_FILE when unable to identify the key format.
*/
static int ProcessBufferTryDecode(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int* keyFormat, void* heap, int type)
{
int ret = 0;
int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
byte* keyType = NULL;
int* keySz = NULL;
(void)heap;
(void)devId;
(void)type;
if ((der == NULL) || (keyFormat == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (ctx == NULL) && (ssl == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (ssl != NULL) {
keyType = &ssl->buffers.altKeyType;
keySz = &ssl->buffers.altKeySz;
}
else {
keyType = &ctx->altPrivateKeyType;
keySz = &ctx->altPrivateKeySz;
}
}
else
#endif
if (ssl != NULL) {
keyType = &ssl->buffers.keyType;
keySz = &ssl->buffers.keySz;
}
else {
keyType = &ctx->privateKeyType;
keySz = &ctx->privateKeySz;
}
}
#ifndef NO_RSA
if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == RSAk))) {
#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \
(HAVE_FIPS_VERSION > 2))
ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keyFormat, devId,
keyType, keySz);
#else
ret = ProcessBufferTryDecodeRsa(ctx, ssl, der, keyFormat, heap, devId,
keyType, keySz);
#endif
}
#endif
#ifdef HAVE_ECC
if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == ECDSAk)
#ifdef WOLFSSL_SM2
|| (*keyFormat == SM2k)
#endif
)) {
ret = ProcessBufferTryDecodeEcc(ctx, ssl, der, keyFormat, heap, devId,
keyType, keySz);
}
#endif
#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_IMPORT)
if ((ret == 0) && ((*keyFormat == 0 || *keyFormat == ED25519k))) {
ret = ProcessBufferTryDecodeEd25519(ctx, ssl, der, keyFormat, heap,
devId, keyType, keySz);
}
#endif
#if defined(HAVE_ED448) && defined(HAVE_ED448_KEY_IMPORT)
if ((ret == 0) && ((*keyFormat == 0 || *keyFormat == ED448k))) {
ret = ProcessBufferTryDecodeEd448(ctx, ssl, der, keyFormat, heap, devId,
keyType, keySz);
}
#endif
#if defined(HAVE_FALCON)
if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == FALCON_LEVEL1k) ||
(*keyFormat == FALCON_LEVEL5k))) {
ret = ProcessBufferTryDecodeFalcon(ctx, ssl, der, keyFormat, heap,
keyType, keySz);
}
#endif
#if defined(HAVE_DILITHIUM) && !defined(WOLFSSL_DILITHIUM_NO_SIGN) && \
!defined(WOLFSSL_DILITHIUM_NO_ASN1)
*/
if ((ret == 0) && ((*keyFormat == 0) || (*keyFormat == DILITHIUM_LEVEL2k) ||
(*keyFormat == DILITHIUM_LEVEL3k) ||
(*keyFormat == DILITHIUM_LEVEL5k))) {
ret = ProcessBufferTryDecodeDilithium(ctx, ssl, der, keyFormat, heap,
keyType, keySz);
}
#endif
if ((ret == 0) && (*keyFormat == 0)) {
WOLFSSL_MSG("Not a supported key type");
ret = WOLFSSL_BAD_FILE;
}
return ret;
}
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
*
* @param [in] info Encryption information.
* @param [in] der DER encoded data.
* @param [in] heap Dynamic memory allocation hint.
* @return 0 on success.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int ProcessBufferPrivPkcs8Dec(EncryptedInfo* info, DerBuffer* der,
void* heap)
{
int ret = 0;
word32 algId;
int passwordSz = NAME_SZ;
#ifndef WOLFSSL_SMALL_STACK
char password[NAME_SZ];
#else
char* password;
#endif
(void)heap;
#ifdef WOLFSSL_SMALL_STACK
password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING);
if (password == NULL) {
ret = MEMORY_E;
}
#endif
if (ret == 0) {
ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ,
info->passwd_userdata);
}
if (ret >= 0) {
passwordSz = ret;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("ProcessBuffer password", password, passwordSz);
#endif
ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz,
&algId);
}
if (ret >= 0) {
ForceZero(der->buffer + ret, der->length - ret);
der->length = (word32)ret;
}
ForceZero(password, (word32)passwordSz);
#ifdef WOLFSSL_SMALL_STACK
XFREE(password, heap, DYNAMIC_TYPE_STRING);
#elif defined(WOLFSSL_CHECK_MEM_ZERO)
wc_MemZero_Check(password, NAME_SZ);
#endif
return ret;
}
#endif
*
* Precondition: ctx or ssl is not NULL.
* Precondition: Must be a private key type.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @return 0 on success.
*/
static int ProcessBufferPrivKeyHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer** der, int type)
{
int ret = 0;
(void)type;
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (ssl != NULL) {
if (ssl->buffers.weOwnAltKey) {
FreeDer(&ssl->buffers.altKey);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.altKeyMask);
#endif
}
ssl->buffers.altKeyId = 0;
ssl->buffers.altKeyLabel = 0;
ssl->buffers.altKeyDevId = INVALID_DEVID;
ssl->buffers.altKey = *der;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("SSL Buffers key", (*der)->buffer, (*der)->length);
#endif
ssl->buffers.weOwnAltKey = 1;
}
else if (ctx != NULL) {
FreeDer(&ctx->altPrivateKey);
ctx->altPrivateKeyId = 0;
ctx->altPrivateKeyLabel = 0;
ctx->altPrivateKeyDevId = INVALID_DEVID;
ctx->altPrivateKey = *der;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length);
#endif
}
}
else
#endif
if (ssl != NULL) {
if (ssl->buffers.weOwnKey) {
FreeDer(&ssl->buffers.key);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.keyMask);
#endif
}
ssl->buffers.keyId = 0;
ssl->buffers.keyLabel = 0;
ssl->buffers.keyDevId = INVALID_DEVID;
ssl->buffers.key = *der;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("SSL Buffers key", (*der)->buffer, (*der)->length);
#endif
ssl->buffers.weOwnKey = 1;
}
else if (ctx != NULL) {
FreeDer(&ctx->privateKey);
ctx->privateKeyId = 0;
ctx->privateKeyLabel = 0;
ctx->privateKeyDevId = INVALID_DEVID;
ctx->privateKey = *der;
#ifdef WOLFSSL_CHECK_MEM_ZERO
wc_MemZero_Add("CTX private key", (*der)->buffer, (*der)->length);
#endif
}
return ret;
}
*
* Precondition: ctx or ssl is not NULL.
* Precondition: Must be a private key type.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoding.
* @param [in] format Original format of data.
* @param [in] info Encryption information.
* @param [in] heap Dynamic memory allocation hint.
* @param [in] type Type of data:
* PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
* @param [in] algId Algorithm id of key.
* @return 0 on success.
* @return WOLFSSL_BAD_FILE when not able to decode.
*/
static int ProcessBufferPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int format, EncryptedInfo* info, void* heap, int type,
int algId)
{
int ret;
#if (defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)) || \
defined(HAVE_PKCS8)
word32 p8AlgId = 0;
#endif
(void)info;
(void)format;
#ifdef HAVE_PKCS8
ret = ToTraditional_ex(der->buffer, der->length, &p8AlgId);
if (ret > 0) {
der->length = (word32)ret;
algId = p8AlgId;
}
#endif
ret = ProcessBufferPrivKeyHandleDer(ctx, ssl, &der, type);
if (ret == 0) {
ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type);
}
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
if (((ret != 0) || (algId == 0)) && (format != WOLFSSL_FILETYPE_PEM) &&
(info->passwd_cb != NULL) && (algId == 0)) {
ret = ProcessBufferPrivPkcs8Dec(info, der, heap);
if (ret >= 0) {
ret = ProcessBufferTryDecode(ctx, ssl, der, &algId, heap, type);
}
}
#endif
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (type == ALT_PRIVATEKEY_TYPE) {
if (ssl != NULL) {
ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.altKey,
&ssl->buffers.altKeyMask);
}
else {
ret = wolfssl_priv_der_blind(NULL, ctx->altPrivateKey,
&ctx->altPrivateKeyMask);
}
}
else
#endif
if (ssl != NULL) {
ret = wolfssl_priv_der_blind(ssl->rng, ssl->buffers.key,
&ssl->buffers.keyMask);
}
else {
ret = wolfssl_priv_der_blind(NULL, ctx->privateKey,
&ctx->privateKeyMask);
}
#endif
if ((ret == 0) && (algId == 0)) {
#ifdef OPENSSL_EXTRA
if (info->passwd_cb) {
EVPerr(0, EVP_R_BAD_DECRYPT);
}
#endif
WOLFSSL_ERROR(WOLFSSL_BAD_FILE);
ret = WOLFSSL_BAD_FILE;
}
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] keyOID OID for public/private key.
*/
static void wolfssl_set_have_from_key_oid(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
int keyOID)
{
switch (keyOID) {
case ECDSAk:
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
case SM2k:
#endif
#ifdef HAVE_ED25519
case ED25519k:
#endif
#ifdef HAVE_ED448
case ED448k:
#endif
if (ssl != NULL) {
ssl->options.haveECC = 1;
}
else {
ctx->haveECC = 1;
}
break;
#ifndef NO_RSA
case RSAk:
#ifdef WC_RSA_PSS
case RSAPSSk:
#endif
if (ssl != NULL) {
ssl->options.haveRSA = 1;
}
else {
ctx->haveRSA = 1;
}
break;
#endif
#ifdef HAVE_FALCON
case FALCON_LEVEL1k:
case FALCON_LEVEL5k:
if (ssl != NULL) {
ssl->options.haveFalconSig = 1;
}
else {
ctx->haveFalconSig = 1;
}
break;
#endif
#ifdef HAVE_DILITHIUM
case DILITHIUM_LEVEL2k:
case DILITHIUM_LEVEL3k:
case DILITHIUM_LEVEL5k:
if (ssl != NULL) {
ssl->options.haveDilithiumSig = 1;
}
else {
ctx->haveDilithiumSig = 1;
}
break;
#endif
default:
WOLFSSL_MSG("Cert key not supported");
break;
}
}
*
* Precondition: ctx or ssl is not NULL.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] cert Decode certificate.
*/
static void ProcessBufferCertSetHave(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DecodedCert* cert)
{
if (ssl != NULL) {
ssl->options.haveECDSAsig = 0;
ssl->options.haveFalconSig = 0;
ssl->options.haveDilithiumSig = 0;
}
switch (cert->signatureOID) {
case CTC_SHAwECDSA:
case CTC_SHA256wECDSA:
case CTC_SHA384wECDSA:
case CTC_SHA512wECDSA:
#ifdef HAVE_ED25519
case CTC_ED25519:
#endif
#ifdef HAVE_ED448
case CTC_ED448:
#endif
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
case CTC_SM3wSM2:
#endif
WOLFSSL_MSG("ECDSA/ED25519/ED448 cert signature");
if (ssl) {
ssl->options.haveECDSAsig = 1;
}
else if (ctx) {
ctx->haveECDSAsig = 1;
}
break;
#ifdef HAVE_FALCON
case CTC_FALCON_LEVEL1:
case CTC_FALCON_LEVEL5:
WOLFSSL_MSG("Falcon cert signature");
if (ssl) {
ssl->options.haveFalconSig = 1;
}
else if (ctx) {
ctx->haveFalconSig = 1;
}
break;
#endif
#ifdef HAVE_DILITHIUM
case CTC_DILITHIUM_LEVEL2:
case CTC_DILITHIUM_LEVEL3:
case CTC_DILITHIUM_LEVEL5:
WOLFSSL_MSG("Dilithium cert signature");
if (ssl) {
ssl->options.haveDilithiumSig = 1;
}
else if (ctx) {
ctx->haveDilithiumSig = 1;
}
break;
#endif
default:
WOLFSSL_MSG("Cert signature not supported");
break;
}
#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
defined(HAVE_FALCON) || defined(HAVE_DILITHIUM) || !defined(NO_RSA)
#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448)
if (ssl != NULL) {
ssl->pkCurveOID = cert->pkCurveOID;
}
else if (ctx) {
ctx->pkCurveOID = cert->pkCurveOID;
}
#endif
#ifndef WC_STRICT_SIG
wolfssl_set_have_from_key_oid(ctx, ssl, cert->keyOID);
#else
if (ssl != NULL) {
ssl->options.haveECC = ssl->options.haveECDSAsig;
}
else if (ctx) {
ctx->haveECC = ctx->haveECDSAsig;
}
#endif
#endif
}
*
* Precondition: ctx or ssl is not NULL.
*
* @param [in] min Minimum key size.
* @param [in] max Maximum key size.
* @param [in] keySz Key size.
* @param [in] err Error value to return when key size is invalid.
* @return 0 on success.
* @return err when verifying and min is less than 0 or key size is invalid.
*/
#define CHECK_KEY_SZ(min, max, keySz, err) \
(((min) < 0) || ((keySz) < (min)) || ((keySz) > (max))) ? (err) : 0
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] cert Certificate object.
* @return 0 on success.
* @return Non-zero when an error occurred.
*/
static int ProcessBufferCertPublicKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DecodedCert* cert, int checkKeySz)
{
int ret = 0;
byte keyType = 0;
int keySz = 0;
#ifndef NO_RSA
word32 idx;
#endif
switch (cert->keyOID) {
#ifndef NO_RSA
#ifdef WC_RSA_PSS
case RSAPSSk:
#endif
case RSAk:
keyType = rsa_sa_algo;
idx = 0;
ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx,
cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL);
if ((ret == 0) && checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minRsaKeySz :
ctx->minRsaKeySz, RSA_MAX_SIZE / 8, keySz, RSA_KEY_SIZE_E);
}
break;
#endif
#ifdef HAVE_ECC
case ECDSAk:
keyType = ecc_dsa_sa_algo;
#ifdef WOLFSSL_CUSTOM_CURVES
if ((cert->pkCurveOID == 0) && (cert->pkCurveSize != 0)) {
keySz = cert->pkCurveSize;
}
else
#endif
{
keySz = wc_ecc_get_curve_size_from_id(wc_ecc_get_oid(
cert->pkCurveOID, NULL, NULL));
}
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
ECC_KEY_SIZE_E);
}
break;
#endif
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
case SM2k:
keyType = sm2_sa_algo;
keySz = WOLFSSL_SM2_KEY_BITS / 8;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
ECC_KEY_SIZE_E);
}
break;
#endif
#ifdef HAVE_ED25519
case ED25519k:
keyType = ed25519_sa_algo;
keySz = ED25519_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, ED25519_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
}
break;
#endif
#ifdef HAVE_ED448
case ED448k:
keyType = ed448_sa_algo;
keySz = ED448_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, ED448_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
}
break;
#endif
#if defined(HAVE_FALCON)
case FALCON_LEVEL1k:
keyType = falcon_level1_sa_algo;
keySz = FALCON_LEVEL1_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
FALCON_KEY_SIZE_E);
}
break;
case FALCON_LEVEL5k:
keyType = falcon_level5_sa_algo;
keySz = FALCON_LEVEL5_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
FALCON_KEY_SIZE_E);
}
break;
#endif
#if defined(HAVE_DILITHIUM)
case DILITHIUM_LEVEL2k:
keyType = dilithium_level2_sa_algo;
keySz = DILITHIUM_LEVEL2_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz,
DILITHIUM_KEY_SIZE_E);
}
break;
case DILITHIUM_LEVEL3k:
keyType = dilithium_level3_sa_algo;
keySz = DILITHIUM_LEVEL3_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz,
DILITHIUM_KEY_SIZE_E);
}
break;
case DILITHIUM_LEVEL5k:
keyType = dilithium_level5_sa_algo;
keySz = DILITHIUM_LEVEL5_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz,
DILITHIUM_KEY_SIZE_E);
}
break;
#endif
default:
WOLFSSL_MSG("No key size check done on public key in certificate");
break;
}
if (ssl != NULL) {
ssl->buffers.keyType = keyType;
ssl->buffers.keySz = keySz;
}
else {
ctx->privateKeyType = keyType;
ctx->privateKeySz = keySz;
}
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
static int ProcessBufferCertAltPublicKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DecodedCert* cert, int checkKeySz)
{
int ret = 0;
void* heap = WOLFSSL_HEAP(ctx, ssl);
byte keyType = 0;
int keySz = 0;
#ifndef NO_RSA
word32 idx;
#endif
switch (cert->sapkiOID) {
case 0:
if (cert->sapkiLen != 0) {
ret = NOT_COMPILED_IN;
}
break;
#ifndef NO_RSA
#ifdef WC_RSA_PSS
case RSAPSSk:
#endif
case RSAk:
keyType = rsa_sa_algo;
idx = 0;
ret = wc_RsaPublicKeyDecode_ex(cert->sapkiDer, &idx,
cert->sapkiLen, NULL, (word32*)&keySz, NULL, NULL);
if ((ret == 0) && checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minRsaKeySz :
ctx->minRsaKeySz, RSA_MAX_SIZE / 8, keySz, RSA_KEY_SIZE_E);
}
break;
#endif
#ifdef HAVE_ECC
case ECDSAk:
{
#ifdef WOLFSSL_SMALL_STACK
ecc_key* temp_key = NULL;
#else
ecc_key temp_key[1];
#endif
keyType = ecc_dsa_sa_algo;
#ifdef WOLFSSL_SMALL_STACK
temp_key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap,
DYNAMIC_TYPE_ECC);
if (temp_key == NULL) {
ret = MEMORY_E;
}
#endif
* that. */
if (ret == 0) {
ret = wc_ecc_init_ex(temp_key, heap, INVALID_DEVID);
if (ret == 0) {
idx = 0;
ret = wc_EccPublicKeyDecode(cert->sapkiDer, &idx, temp_key,
cert->sapkiLen);
if (ret == 0) {
keySz = wc_ecc_size(temp_key);
}
wc_ecc_free(temp_key);
}
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(temp_key, heap, DYNAMIC_TYPE_ECC);
#endif
if ((ret == 0) && checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
ECC_KEY_SIZE_E);
}
break;
}
#endif
#if defined(WOLFSSL_SM2) && defined(WOLFSSL_SM3)
case SM2k:
keyType = sm2_sa_algo;
keySz = WOLFSSL_SM2_KEY_BITS / 8;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, (MAX_ECC_BITS + 7) / 8, keySz,
ECC_KEY_SIZE_E);
}
break;
#endif
#ifdef HAVE_ED25519
case ED25519k:
keyType = ed25519_sa_algo;
keySz = ED25519_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, ED25519_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
}
break;
#endif
#ifdef HAVE_ED448
case ED448k:
keyType = ed448_sa_algo;
keySz = ED448_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minEccKeySz :
ctx->minEccKeySz, ED448_KEY_SIZE, keySz, ECC_KEY_SIZE_E);
}
break;
#endif
#if defined(HAVE_FALCON)
case FALCON_LEVEL1k:
keyType = falcon_level1_sa_algo;
keySz = FALCON_LEVEL1_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
FALCON_KEY_SIZE_E);
}
break;
case FALCON_LEVEL5k:
keyType = falcon_level5_sa_algo;
keySz = FALCON_LEVEL5_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minFalconKeySz :
ctx->minFalconKeySz, FALCON_MAX_KEY_SIZE, keySz,
FALCON_KEY_SIZE_E);
}
break;
#endif
#if defined(HAVE_DILITHIUM)
case DILITHIUM_LEVEL2k:
keyType = dilithium_level2_sa_algo;
keySz = DILITHIUM_LEVEL2_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz,
DILITHIUM_KEY_SIZE_E);
}
break;
case DILITHIUM_LEVEL3k:
keyType = dilithium_level3_sa_algo;
keySz = DILITHIUM_LEVEL3_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz,
DILITHIUM_KEY_SIZE_E);
}
break;
case DILITHIUM_LEVEL5k:
keyType = dilithium_level5_sa_algo;
keySz = DILITHIUM_LEVEL5_KEY_SIZE;
if (checkKeySz) {
ret = CHECK_KEY_SZ(ssl ? ssl->options.minDilithiumKeySz :
ctx->minDilithiumKeySz, DILITHIUM_MAX_KEY_SIZE, keySz,
DILITHIUM_KEY_SIZE_E);
}
break;
#endif
default:
* This is an error. Use not compiled in because likely the
* given algorithm was not enabled. */
ret = NOT_COMPILED_IN;
WOLFSSL_MSG("No alt key size check done on certificate");
break;
}
if (ssl != NULL) {
ssl->buffers.altKeyType = (byte)keyType;
ssl->buffers.altKeySz = keySz;
}
else if (ctx != NULL) {
ctx->altPrivateKeyType = (byte)keyType;
ctx->altPrivateKeySz = keySz;
}
return ret;
}
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoded X509 certificate.
* @return 0 on success.
* @return MEMORY_E when dynamic memory allocation fails.
* @return WOLFSSL_BAD_FILE when decoding certificate fails.
*/
static int ProcessBufferCert(WOLFSSL_CTX* ctx, WOLFSSL* ssl, DerBuffer* der)
{
int ret = 0;
void* heap = WOLFSSL_HEAP(ctx, ssl);
#if defined(HAVE_RPK)
RpkState* rpkState = ssl ? &ssl->options.rpkState : &ctx->rpkState;
#endif
#ifdef WOLFSSL_SMALL_STACK
DecodedCert* cert;
#else
DecodedCert cert[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, DYNAMIC_TYPE_DCERT);
if (cert == NULL) {
ret = MEMORY_E;
}
if (ret == 0)
#endif
{
int devId = wolfSSL_CTX_GetDevId(ctx, ssl);
WOLFSSL_MSG("Checking cert signature type");
InitDecodedCert_ex(cert, der->buffer, der->length, heap, devId);
if (DecodeToKey(cert, 0) < 0) {
WOLFSSL_MSG("Decode to key failed");
ret = WOLFSSL_BAD_FILE;
}
if (ret == 0) {
int checkKeySz = 1;
#if defined(HAVE_RPK)
rpkState->isRPKLoaded = cert->isRPK;
#endif
ProcessBufferCertSetHave(ctx, ssl, cert);
if ((ssl != NULL) && ssl->options.verifyNone) {
checkKeySz = 0;
}
* context. */
else if ((ssl == NULL) && ctx->verifyNone) {
checkKeySz = 0;
}
ret = ProcessBufferCertPublicKey(ctx, ssl, cert, checkKeySz);
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ret == 0) {
ret = ProcessBufferCertAltPublicKey(ctx, ssl, cert, checkKeySz);
}
#endif
}
}
FreeDecodedCert(cert);
#ifdef WOLFSSL_SMALL_STACK
XFREE(cert, heap, DYNAMIC_TYPE_DCERT);
#endif
return ret;
}
*
* Do not free der outside of this function.
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] der DER encoded certificate.
* @param [in] type Type of data:
* CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE.
* @param [in] verify What verification to do.
* @return 0 on success.
* @return BAD_FUNC_ARG when type is CA_TYPE and ctx is NULL.
* @return WOLFSSL_BAD_CERTTYPE when data type is not supported.
*/
static int ProcessBufferCertHandleDer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
DerBuffer* der, int type, int verify)
{
int ret = 0;
if (type == CA_TYPE) {
ret = AddCA(ctx->cm, &der, WOLFSSL_USER_CA, verify);
if (ret == 1) {
ret = 0;
}
}
#ifdef WOLFSSL_TRUST_PEER_CERT
else if (type == TRUSTED_PEER_TYPE) {
WOLFSSL_CERT_MANAGER* cm;
if (ctx != NULL) {
cm = ctx->cm;
}
else {
SSL_CM_WARNING(ssl);
cm = SSL_CM(ssl);
}
ret = AddTrustedPeer(cm, &der, verify);
if (ret != 1) {
WOLFSSL_MSG("Error adding trusted peer");
}
}
#endif
else if (type == CERT_TYPE) {
if (ssl != NULL) {
if (ssl->buffers.weOwnCert) {
FreeDer(&ssl->buffers.certificate);
#ifdef KEEP_OUR_CERT
wolfSSL_X509_free(ssl->ourCert);
ssl->ourCert = NULL;
#endif
}
ssl->buffers.certificate = der;
#ifdef KEEP_OUR_CERT
ssl->keepCert = 1;
#endif
ssl->buffers.weOwnCert = 1;
}
else if (ctx != NULL) {
FreeDer(&ctx->certificate);
#ifdef KEEP_OUR_CERT
if (ctx->ownOurCert) {
wolfSSL_X509_free(ctx->ourCert);
}
ctx->ourCert = NULL;
#endif
ctx->certificate = der;
}
}
else {
FreeDer(&der);
ret = WOLFSSL_BAD_CERTTYPE;
}
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] buff Buffer holding original data.
* @param [in] sz Size of data in buffer.
* @param [in] der DER encoding of certificate.
* @param [in] format Format of data.
* @param [in] type Type of data:
* CERT_TYPE, CA_TYPE or TRUSTED_PEER_TYPE.
* @param [in] verify What verification to do.
* @return 0 on success.
* @return WOLFSSL_FATAL_ERROR on failure.
*/
static int ProcessBufferCertTypes(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const unsigned char* buff, long sz, DerBuffer* der, int format, int type,
int verify)
{
int ret;
(void)buff;
(void)sz;
(void)format;
ret = ProcessBufferCertHandleDer(ctx, ssl, der, type, verify);
if ((ret == 0) && (type == CERT_TYPE)) {
ret = ProcessBufferCert(ctx, ssl, der);
}
#if !defined(NO_WOLFSSL_CM_VERIFY) && (!defined(NO_WOLFSSL_CLIENT) || \
!defined(WOLFSSL_NO_CLIENT_AUTH))
if ((ret < 0) && ((type == CA_TYPE) || (type == CERT_TYPE))) {
if ((ctx != NULL) && (ctx->cm != NULL) &&
(ctx->cm->verifyCallback != NULL)) {
ret = CM_VerifyBuffer_ex(ctx->cm, buff, sz, format, ret);
if (ret == 0) {
ret = WOLFSSL_FATAL_ERROR;
}
if (ret == 1) {
ret = 0;
}
}
}
#endif
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] type Type of certificate.
* @return 0 on success.
* @return WOLFSSL_FATAL_ERROR when allocation fails.
*/
static int ProcessBufferResetSuites(WOLFSSL_CTX* ctx, WOLFSSL* ssl, int type)
{
int ret = 0;
if (ssl != NULL) {
if (ssl->options.side == WOLFSSL_SERVER_END) {
if (AllocateSuites(ssl) != 0) {
ret = WOLFSSL_FATAL_ERROR;
}
else {
InitSuites(ssl->suites, ssl->version, ssl->buffers.keySz,
WOLFSSL_HAVE_RSA, SSL_HAVE_PSK(ssl), ssl->options.haveDH,
ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE,
ssl->options.haveStaticECC, ssl->options.haveFalconSig,
ssl->options.haveDilithiumSig, ssl->options.useAnon, TRUE,
ssl->options.side);
}
}
}
else if ((type == CERT_TYPE) && (ctx->method->side == WOLFSSL_SERVER_END)) {
if (AllocateCtxSuites(ctx) != 0) {
ret = WOLFSSL_FATAL_ERROR;
}
else {
InitSuites(ctx->suites, ctx->method->version, ctx->privateKeySz,
WOLFSSL_HAVE_RSA, CTX_HAVE_PSK(ctx), ctx->haveDH,
ctx->haveECDSAsig, ctx->haveECC, TRUE, ctx->haveStaticECC,
ctx->haveFalconSig, ctx->haveDilithiumSig, CTX_USE_ANON(ctx),
TRUE, ctx->method->side);
}
}
return ret;
}
#ifndef WOLFSSL_DUAL_ALG_CERTS
#define IS_PRIVKEY_TYPE(type) ((type) == PRIVATEKEY_TYPE)
#else
#define IS_PRIVKEY_TYPE(type) (((type) == PRIVATEKEY_TYPE) || \
((type) == ALT_PRIVATEKEY_TYPE))
#endif
*
* Data type is a private key or a certificate.
* The format can be ASN.1 (DER) or PEM.
*
* @param [in, out] ctx SSL context object.
* @param [in] buff Buffer holding data.
* @param [in] sz Size of data in buffer.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @param [in] type Type of data:
* CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE,
* PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
* @param [in, out] ssl SSL object.
* @param [out] used Number of bytes consumed.
* @param [in[ userChain Whether this certificate is for user's chain.
* @param [in] verify How to verify certificate.
* @return 1 on success.
* @return Less than 1 on failure.
*/
int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, long sz,
int format, int type, WOLFSSL* ssl, long* used, int userChain, int verify)
{
DerBuffer* der = NULL;
int ret = 0;
void* heap = WOLFSSL_HEAP(ctx, ssl);
#ifdef WOLFSSL_SMALL_STACK
EncryptedInfo* info = NULL;
#else
EncryptedInfo info[1];
#endif
int algId = 0;
WOLFSSL_ENTER("ProcessBuffer");
if ((format != WOLFSSL_FILETYPE_ASN1) && (format != WOLFSSL_FILETYPE_PEM)) {
ret = WOLFSSL_BAD_FILETYPE;
}
if ((ret == 0) && (ctx == NULL) && (ssl == NULL)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (ctx == NULL) && (type == CA_TYPE)) {
ret = BAD_FUNC_ARG;
}
if ((ret == 0) && (type == CHAIN_CERT_TYPE)) {
ret = BAD_FUNC_ARG;
}
#ifdef WOLFSSL_SMALL_STACK
if (ret == 0) {
info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap,
DYNAMIC_TYPE_ENCRYPTEDINFO);
if (info == NULL) {
ret = MEMORY_E;
}
}
#endif
if (ret == 0) {
XMEMSET(info, 0, sizeof(EncryptedInfo));
#if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_PWDBASED)
if (ctx != NULL) {
info->passwd_cb = ctx->passwd_cb;
info->passwd_userdata = ctx->passwd_userdata;
}
#endif
ret = DataToDerBuffer(buff, (word32)sz, format, type, info, heap, &der,
&algId);
if (used != NULL) {
*used = info->consumed;
}
#ifdef WOLFSSL_SMALL_STACK
if (ret != 0) {
XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
}
#endif
}
if ((ret == 0) && IS_PRIVKEY_TYPE(type)) {
ret = ProcessBufferPrivateKey(ctx, ssl, der, format, info, heap, type,
algId);
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
}
else if (ret == 0) {
if (userChain) {
* handshake. */
ret = ProcessUserChain(ctx, ssl, buff, sz, format, type, used, info,
verify);
if (ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)) {
unsigned long pemErr = 0;
CLEAR_ASN_NO_PEM_HEADER_ERROR(pemErr);
ret = 0;
}
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO);
#endif
if (ret == 0) {
ret = ProcessBufferCertTypes(ctx, ssl, buff, sz, der, format, type,
verify);
}
else {
FreeDer(&der);
}
}
if ((ret == 0) && ((type == PRIVATEKEY_TYPE) || (type == CERT_TYPE))) {
ret = ProcessBufferResetSuites(ctx, ssl, type);
}
if (ret == 0) {
ret = 1;
}
else if (ret == WOLFSSL_FATAL_ERROR) {
ret = 0;
}
WOLFSSL_LEAVE("ProcessBuffer", ret);
return ret;
}
#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
*
* @param [in] ctx SSL context object.
* @param [in] buff Buffer containing potential CRL in PEM format.
* @param [in] sz Amount of data in buffer remaining.
* @param [out] consumed Number of bytes in buffer was the CRL.
* @return 0 on success.
*/
static int ProcessChainBufferCRL(WOLFSSL_CTX* ctx, const unsigned char* buff,
long sz, long* consumed)
{
int ret;
DerBuffer* der = NULL;
EncryptedInfo info;
WOLFSSL_MSG("Trying a CRL");
ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, NULL);
if (ret == 0) {
WOLFSSL_MSG(" Processed a CRL");
wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, der->length,
WOLFSSL_FILETYPE_ASN1);
FreeDer(&der);
*consumed = info.consumed;
}
return ret;
}
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] buff Buffer containing PEM data.
* @param [in] sz Size of data in buffer.
* @param [in] type Type of data.
* @param [in] verify How to verify certificate.
* @return 1 on success.
* @return 0 on failure.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int ProcessChainBuffer(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const unsigned char* buff, long sz, int type, int verify)
{
int ret = 0;
long used = 0;
int gotOne = 0;
WOLFSSL_MSG("Processing CA PEM file");
while ((ret >= 0) && (used < sz)) {
long consumed = 0;
ret = ProcessBuffer(ctx, buff + used, sz - used, WOLFSSL_FILETYPE_PEM,
type, ssl, &consumed, 0, verify);
if (ret == WC_NO_ERR_TRACE(MEMORY_E)) {
gotOne = 0;
}
else if (ret < 0) {
#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
if (ProcessChainBufferCRL(ctx, buff + used, sz - used,
&consumed) == 0) {
ret = 0;
}
else
#endif
if (consumed > 0) {
WOLFSSL_ERROR(ret);
WOLFSSL_MSG("CA Parse failed, with progress in file.");
WOLFSSL_MSG("Search for other certs in file");
if (used + consumed < sz) {
ret = 0;
}
}
else {
WOLFSSL_MSG("CA Parse failed, no progress in file.");
WOLFSSL_MSG("Do not continue search for other certs in file");
}
}
else {
WOLFSSL_MSG(" Processed a CA");
gotOne = 1;
}
used += consumed;
}
if (gotOne) {
WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK");
ret = 1;
}
return ret;
}
#define GET_VERIFY_SETTING_CTX(ctx) \
((ctx) && (ctx)->verifyNone ? NO_VERIFY : VERIFY)
#define GET_VERIFY_SETTING_SSL(ssl) \
((ssl)->options.verifyNone ? NO_VERIFY : VERIFY)
#ifndef NO_FILESYSTEM
*
* @param [in, out] ctx SSL context object.
* @param [in] fname Name of file to read.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @param [in] type Type of data:
* CERT_TYPE, CA_TYPE, TRUSTED_PEER_TYPE,
* PRIVATEKEY_TYPE or ALT_PRIVATEKEY_TYPE.
* @param [in, out] ssl SSL object.
* @param [in] userChain Whether file contains chain of certificates.
* @param [in, out] crl CRL object to load data into.
* @param [in] verify How to verify certificates.
* @return 1 on success.
* @return WOLFSSL_BAD_FILE when reading the file fails.
* @return WOLFSSL_BAD_CERTTYPE when unable to detect certificate type.
*/
int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type,
WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl, int verify)
{
int ret = 0;
#ifndef WOLFSSL_SMALL_STACK
byte stackBuffer[FILE_BUFFER_SIZE];
#endif
StaticBuffer content;
long sz = 0;
void* heap = WOLFSSL_HEAP(ctx, ssl);
(void)crl;
(void)heap;
#ifdef WOLFSSL_SMALL_STACK
static_buffer_init(&content);
#else
static_buffer_init(&content, stackBuffer, FILE_BUFFER_SIZE);
#endif
ret = wolfssl_read_file_static(fname, &content, heap, DYNAMIC_TYPE_FILE,
&sz);
if ((ret == 0) && (type == DETECT_CERT_TYPE) &&
(format != WOLFSSL_FILETYPE_PEM)) {
WOLFSSL_MSG("Cannot detect certificate type when not PEM");
ret = WOLFSSL_BAD_CERTTYPE;
}
if ((ret == 0) && (type == DETECT_CERT_TYPE)) {
#if !defined(NO_CODING) && !defined(WOLFSSL_NO_PEM)
const char* header = NULL;
const char* footer = NULL;
if (wc_PemGetHeaderFooter(CA_TYPE, &header, &footer) == 0 &&
(XSTRNSTR((char*)content.buffer, header, (word32)sz) != NULL)) {
type = CA_TYPE;
}
#ifdef HAVE_CRL
else if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 &&
(XSTRNSTR((char*)content.buffer, header, (word32)sz) != NULL)) {
type = CRL_TYPE;
}
#endif
else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 &&
(XSTRNSTR((char*)content.buffer, header, (word32)sz) !=
NULL)) {
type = CERT_TYPE;
}
else
#endif
{
WOLFSSL_MSG("Failed to detect certificate type");
ret = WOLFSSL_BAD_CERTTYPE;
}
}
if (ret == 0) {
if (((type == CA_TYPE) || (type == TRUSTED_PEER_TYPE)) &&
(format == WOLFSSL_FILETYPE_PEM)) {
ret = ProcessChainBuffer(ctx, ssl, content.buffer, sz, type,
verify);
}
#ifdef HAVE_CRL
else if (type == CRL_TYPE) {
ret = BufferLoadCRL(crl, content.buffer, sz, format, verify);
}
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
else if (type == PRIVATEKEY_TYPE) {
* private key file may contain both the primary and the
* alternative private key. Hence, we have to parse both of them.
*/
long consumed = 0;
ret = ProcessBuffer(ctx, content.buffer, sz, format, type, ssl,
&consumed, userChain, verify);
if ((ret == 1) && (consumed < sz)) {
ret = ProcessBuffer(ctx, content.buffer + consumed,
sz - consumed, format, ALT_PRIVATEKEY_TYPE, ssl, NULL, 0,
verify);
}
}
#endif
else {
ret = ProcessBuffer(ctx, content.buffer, sz, format, type, ssl,
NULL, userChain, verify);
}
}
static_buffer_free(&content, heap, DYNAMIC_TYPE_FILE);
return ret;
}
#ifndef NO_WOLFSSL_DIR
*
* @param [in, out] ctx SSL context object.
* @param [in] name Name of file.
* @param [in] verify How to verify a certificate.
* @param [in] flags Flags representing options for loading.
* @param [in, out] failCount Number of files that failed to load.
* @param [in, out] successCount Number of files successfully loaded.
* @return 1 on success.
* @return Not 1 when loading PEM certificate failed.
*/
static int wolfssl_ctx_load_path_file(WOLFSSL_CTX* ctx, const char* name,
int verify, int flags, int* failCount, int* successCount)
{
int ret;
ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL,
verify);
if (ret != 1) {
if ((flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) ||
((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) &&
(ret == WC_NO_ERR_TRACE(ASN_NO_PEM_HEADER)))) {
unsigned long err = 0;
CLEAR_ASN_NO_PEM_HEADER_ERROR(err);
#if defined(WOLFSSL_QT)
ret = 1;
#endif
}
else {
WOLFSSL_ERROR(ret);
WOLFSSL_MSG("Load CA file failed, continuing");
(*failCount)++;
}
}
else {
#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
ret = wolfSSL_CTX_trust_peer_cert(ctx, name, WOLFSSL_FILETYPE_PEM);
if (ret != 1) {
WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error. "
"Ignoring this error.");
}
#endif
(*successCount)++;
}
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] path Path to directory to read.
* @param [in] flags Flags representing options for loading.
* @param [in] verify How to verify a certificate.
* @param [in] successCount Number of files successfully loaded.
* @return 1 on success.
* @return 0 on failure.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int wolfssl_ctx_load_path(WOLFSSL_CTX* ctx, const char* path,
word32 flags, int verify, int successCount)
{
int ret = 1;
char* name = NULL;
int fileRet;
int failCount = 0;
#ifdef WOLFSSL_SMALL_STACK
ReadDirCtx* readCtx;
#else
ReadDirCtx readCtx[1];
#endif
#ifdef WOLFSSL_SMALL_STACK
readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap,
DYNAMIC_TYPE_DIRCTX);
if (readCtx == NULL) {
ret = MEMORY_E;
}
#endif
if (ret == 1) {
fileRet = wc_ReadDirFirst(readCtx, path, &name);
*/
while ((fileRet == 0) && (name != NULL)) {
WOLFSSL_MSG(name);
ret = wolfssl_ctx_load_path_file(ctx, name, verify, (int)flags,
&failCount, &successCount);
fileRet = wc_ReadDirNext(readCtx, path, &name);
}
wc_ReadDirClose(readCtx);
(void)ret;
if (fileRet != WC_READDIR_NOFILE) {
ret = fileRet;
#if defined(WOLFSSL_QT) || defined(WOLFSSL_IGNORE_BAD_CERT_PATH)
if ((ret == WC_NO_ERR_TRACE(BAD_PATH_ERROR)) &&
(flags & WOLFSSL_LOAD_FLAG_IGNORE_BAD_PATH_ERR)) {
* when it is initialized.
* Compliant with OpenSSL when flag set.
*/
ret = 1;
}
else {
WOLFSSL_ERROR(ret);
}
#endif
}
* failures. */
else if ((successCount == 0) || (failCount > 0)) {
#if defined(WOLFSSL_QT)
if (!(flags & WOLFSSL_LOAD_FLAG_IGNORE_ZEROFILE))
#endif
{
ret = 0;
}
}
else {
ret = 1;
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX);
#endif
}
return ret;
}
#endif
*
* No c_rehash.
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of file to load. May be NULL.
* @param [in] path Path to directory containing PEM CA files.
* May be NULL.
* @param [in] flags Flags representing options for loading.
* @return 1 on success.
* @return 0 on failure.
* @return NOT_COMPILED_IN when directory reading not supported and path is
* not NULL.
* @return Other negative on error.
*/
int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file,
const char* path, word32 flags)
{
int ret = 1;
#ifndef NO_WOLFSSL_DIR
int successCount = 0;
#endif
int verify = WOLFSSL_VERIFY_DEFAULT;
WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex");
if ((ctx == NULL) || ((file == NULL) && (path == NULL))) {
ret = 0;
}
if (ret == 1) {
verify = GET_VERIFY_SETTING_CTX(ctx);
if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) {
verify = VERIFY_SKIP_DATE;
}
if (file != NULL) {
ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0,
NULL, verify);
#ifndef NO_WOLFSSL_DIR
if (ret == 1) {
successCount++;
}
#endif
#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
ret = wolfSSL_CTX_trust_peer_cert(ctx, file, WOLFSSL_FILETYPE_PEM);
if (ret != 1) {
WOLFSSL_MSG("wolfSSL_CTX_trust_peer_cert error");
}
#endif
}
}
if ((ret == 1) && (path != NULL)) {
#ifndef NO_WOLFSSL_DIR
ret = wolfssl_ctx_load_path(ctx, path, flags, verify, successCount);
#else
ret = NOT_COMPILED_IN;
(void)flags;
#endif
}
return ret;
}
*
* No c_rehash.
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of file to load. May be NULL.
* @param [in] path Path to directory containing PEM CA files.
* May be NULL.
* @return 1 on success.
* @return 0 on failure.
*/
WOLFSSL_ABI
int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
const char* path)
{
int ret = wolfSSL_CTX_load_verify_locations_ex(ctx, file, path,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
return WS_RETURN_CODE(ret, 0);
}
#ifdef WOLFSSL_SYS_CA_CERTS
#ifdef USE_WINDOWS_API
*
* Assumes loaded is 0.
*
* @param [in, out] ctx SSL context object.
* @param [out] loaded Whether CA certificates were loaded.
* @return 1 on success.
* @return 0 on failure.
*/
static int LoadSystemCaCertsWindows(WOLFSSL_CTX* ctx, byte* loaded)
{
int ret = 1;
word32 i;
HANDLE handle = NULL;
PCCERT_CONTEXT certCtx = NULL;
LPCSTR storeNames[2] = {"ROOT", "CA"};
HCRYPTPROV_LEGACY hProv = (HCRYPTPROV_LEGACY)NULL;
if ((ctx == NULL) || (loaded == NULL)) {
ret = 0;
}
for (i = 0; (ret == 1) && (i < sizeof(storeNames)/sizeof(*storeNames));
++i) {
handle = CertOpenSystemStoreA(hProv, storeNames[i]);
if (handle != NULL) {
while ((certCtx = CertEnumCertificatesInStore(handle, certCtx))
!= NULL) {
if (certCtx->dwCertEncodingType == X509_ASN_ENCODING) {
if (ProcessBuffer(ctx, certCtx->pbCertEncoded,
certCtx->cbCertEncoded, WOLFSSL_FILETYPE_ASN1,
CA_TYPE, NULL, NULL, 0,
GET_VERIFY_SETTING_CTX(ctx)) == 1) {
* Set "loaded" as long as we've loaded one CA
* cert.
*/
*loaded = 1;
}
}
}
}
else {
WOLFSSL_MSG_EX("Failed to open cert store %s.", storeNames[i]);
}
if (handle != NULL && !CertCloseStore(handle, 0)) {
WOLFSSL_MSG_EX("Failed to close cert store %s.", storeNames[i]);
ret = 0;
}
}
return ret;
}
#elif defined(__APPLE__)
#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \
&& !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
* directly into wolfSSL "the old way".
*
* As of MacOS 14.0 we are still able to use this method to access system
* certificates. Accessibility of this API is indicated by the presence of the
* Security/SecTrustSettings.h header. In the likely event that Apple removes
* access to this API on Macs, this function should be removed and the
* DoAppleNativeCertValidation() routine should be used for all devices.
*
* Assumes loaded is 0.
*
* @param [in, out] ctx SSL context object.
* @param [out] loaded Whether CA certificates were loaded.
* @return 1 on success.
* @return 0 on failure.
*/
static int LoadSystemCaCertsMac(WOLFSSL_CTX* ctx, byte* loaded)
{
int ret = 1;
word32 i;
const unsigned int trustDomains[] = {
kSecTrustSettingsDomainUser,
kSecTrustSettingsDomainAdmin,
kSecTrustSettingsDomainSystem
};
CFArrayRef certs;
OSStatus stat;
CFIndex numCerts;
CFDataRef der;
CFIndex j;
if ((ctx == NULL) || (loaded == NULL)) {
ret = 0;
}
for (i = 0; (ret == 1) && (i < sizeof(trustDomains)/sizeof(*trustDomains));
++i) {
stat = SecTrustSettingsCopyCertificates(
(SecTrustSettingsDomain)trustDomains[i], &certs);
if (stat == errSecSuccess) {
numCerts = CFArrayGetCount(certs);
for (j = 0; j < numCerts; ++j) {
der = SecCertificateCopyData((SecCertificateRef)
CFArrayGetValueAtIndex(certs, j));
if (der != NULL) {
if (ProcessBuffer(ctx, CFDataGetBytePtr(der),
CFDataGetLength(der), WOLFSSL_FILETYPE_ASN1,
CA_TYPE, NULL, NULL, 0,
GET_VERIFY_SETTING_CTX(ctx)) == 1) {
* Set "loaded" as long as we've loaded one CA
* cert.
*/
*loaded = 1;
}
CFRelease(der);
}
}
CFRelease(certs);
}
else if (stat == errSecNoTrustSettings) {
WOLFSSL_MSG_EX("No trust settings for domain %d, moving to next "
"domain.", trustDomains[i]);
}
else {
WOLFSSL_MSG_EX("SecTrustSettingsCopyCertificates failed with"
" status %d.", stat);
ret = 0;
break;
}
}
return ret;
}
#endif
#else
static const char* systemCaDirs[] = {
#if defined(__ANDROID__) || defined(ANDROID)
"/system/etc/security/cacerts"
#else
"/etc/ssl/certs",
"/etc/pki/ca-trust/source/anchors",
"/etc/pki/tls/certs"
#endif
};
*
* @param [out] num Number of CA directories.
* @return CA directory list.
* @return NULL when num is NULL.
*/
const char** wolfSSL_get_system_CA_dirs(word32* num)
{
const char** ret;
if (num == NULL) {
ret = NULL;
}
else {
ret = systemCaDirs;
*num = sizeof(systemCaDirs)/sizeof(*systemCaDirs);
}
return ret;
}
*
* Assumes loaded is 0.
*
* @param [in, out] ctx SSL context object.
* @param [out] loaded Whether CA certificates were loaded.
* @return 1 on success.
* @return 0 on failure.
*/
static int LoadSystemCaCertsNix(WOLFSSL_CTX* ctx, byte* loaded) {
int ret = 1;
word32 i;
if ((ctx == NULL) || (loaded == NULL)) {
ret = 0;
}
for (i = 0; (ret == 1) && (i < sizeof(systemCaDirs)/sizeof(*systemCaDirs));
++i) {
WOLFSSL_MSG_EX("Attempting to load system CA certs from %s.",
systemCaDirs[i]);
* We want to keep trying to load more CA certs even if one cert in
* the directory is bad and can't be used (e.g. if one is expired),
* so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR.
*/
if (wolfSSL_CTX_load_verify_locations_ex(ctx, NULL, systemCaDirs[i],
WOLFSSL_LOAD_FLAG_IGNORE_ERR) != 1) {
WOLFSSL_MSG_EX("Failed to load CA certs from %s, trying "
"next possible location.", systemCaDirs[i]);
}
else {
WOLFSSL_MSG_EX("Loaded CA certs from %s.",
systemCaDirs[i]);
*loaded = 1;
break;
}
}
return ret;
}
#endif
*
* @param [in, out] ctx SSL context object.
* @return 1 on success.
* @return 0 on failure.
* @return WOLFSSL_BAD_PATH when no error but no certificates loaded.
*/
int wolfSSL_CTX_load_system_CA_certs(WOLFSSL_CTX* ctx)
{
int ret;
byte loaded = 0;
WOLFSSL_ENTER("wolfSSL_CTX_load_system_CA_certs");
#ifdef USE_WINDOWS_API
ret = LoadSystemCaCertsWindows(ctx, &loaded);
#elif defined(__APPLE__)
#if defined(HAVE_SECURITY_SECTRUSTSETTINGS_H) \
&& !defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
* load them manually into wolfSSL "the old way". Accessibility of this API
* is indicated by the presence of the Security/SecTrustSettings.h header */
ret = LoadSystemCaCertsMac(ctx, &loaded);
#elif defined(WOLFSSL_APPLE_NATIVE_CERT_VALIDATION)
* certificates from the trust store, so we can't use wolfSSL's built-in
* certificate validation mechanisms anymore. We instead must call into the
* Security Framework APIs to authenticate peer certificates when received.
* (see src/internal.c:DoAppleNativeCertValidation()).
* Thus, there is no CA "loading" required, but to keep behavior consistent
* with the current API (not using system CA certs unless this function has
* been called), we simply set a flag indicating that the new apple trust
* verification routine should be used later */
ctx->doAppleNativeCertValidationFlag = 1;
ret = 1;
loaded = 1;
#if FIPS_VERSION_GE(2,0)
#warning "Cryptographic operations may occur outside the FIPS module boundary" \
"Please review FIPS claims for cryptography on this Apple device"
#endif
#else
* system for the required SDK headers. If building with user_settings.h, you
* will need to manually define WOLFSSL_APPLE_NATIVE_CERT_VALIDATION
* and ensure the appropriate Security.framework headers and libraries are
* visible to your compiler */
#error "WOLFSSL_SYS_CA_CERTS on Apple devices requires Security.framework" \
" header files to be detected, or a manual override with" \
" WOLFSSL_APPLE_NATIVE_CERT_VALIDATION"
#endif
#else
ret = LoadSystemCaCertsNix(ctx, &loaded);
#endif
if ((ret == 1) && (!loaded)) {
ret = WOLFSSL_BAD_PATH;
}
WOLFSSL_LEAVE("wolfSSL_CTX_load_system_CA_certs", ret);
return ret;
}
#endif
#ifdef WOLFSSL_TRUST_PEER_CERT
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of peer certificate file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 when ctx or file is NULL.
*/
int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert");
if ((ctx == NULL) || (file == NULL)) {
ret = 0;
}
else {
ret = ProcessFile(ctx, file, format, TRUSTED_PEER_TYPE, NULL, 0, NULL,
GET_VERIFY_SETTING_CTX(ctx));
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] file Name of peer certificate file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 when ssl or file is NULL.
*/
int wolfSSL_trust_peer_cert(WOLFSSL* ssl, const char* file, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_trust_peer_cert");
if ((ssl == NULL) || (file == NULL)) {
ret = 0;
}
else {
ret = ProcessFile(NULL, file, format, TRUSTED_PEER_TYPE, ssl, 0, NULL,
GET_VERIFY_SETTING_SSL(ssl));
}
return ret;
}
#endif
#ifdef WOLFSSL_DER_LOAD
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of peer certificate file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file,
int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations");
if ((ctx == NULL) || (file == NULL)) {
ret = 0;
}
else {
ret = ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL,
GET_VERIFY_SETTING_CTX(ctx));
}
return WS_RC(ret);
}
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of user certificate file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
*/
WOLFSSL_ABI
int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file,
int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file");
ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL,
GET_VERIFY_SETTING_CTX(ctx));
return WS_RC(ret);
}
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of private key file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
*/
WOLFSSL_ABI
int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file");
ret = ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL,
GET_VERIFY_SETTING_CTX(ctx));
return WS_RC(ret);
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of private key file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_AltPrivateKey_file(WOLFSSL_CTX* ctx, const char* file,
int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_file");
ret = ProcessFile(ctx, file, format, ALT_PRIVATEKEY_TYPE, NULL, 0, NULL,
GET_VERIFY_SETTING_CTX(ctx));
return WS_RC(ret);
}
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of PEM certificate chain file.
* @return 1 on success.
* @return 0 on failure.
*/
WOLFSSL_ABI
int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file");
ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, NULL, 1, NULL,
GET_VERIFY_SETTING_CTX(ctx));
return WS_RC(ret);
}
*
* Processes up to MAX_CHAIN_DEPTH plus subject cert.
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of private key file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx,
const char* file, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format");
ret = ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL,
GET_VERIFY_SETTING_CTX(ctx));
return WS_RC(ret);
}
#endif
#ifdef OPENSSL_EXTRA
*
* @param [in, out] ssl SSL object.
* @param [in] pkey EVP private key.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_PrivateKey");
if ((ssl == NULL) || (pkey == NULL)) {
ret = 0;
}
else {
ret = wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr,
pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1);
}
return ret;
}
*
* @param [in] pri Indicates type of private key. Ignored.
* @param [in, out] ssl SSL object.
* @param [in] der Buffer holding DER encoded private key.
* @param [in] derSz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, const unsigned char* der,
long derSz)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1");
(void)pri;
if ((ssl == NULL) || (der == NULL)) {
ret = 0;
}
else {
ret = wolfSSL_use_PrivateKey_buffer(ssl, der, derSz,
WOLFSSL_FILETYPE_ASN1);
}
return ret;
}
*
* @param [in] pri Indicates type of private key. Ignored.
* @param [in, out] ctx SSL context object.
* @param [in] der Buffer holding DER encoded private key.
* @param [in] derSz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_PrivateKey_ASN1(int pri, WOLFSSL_CTX* ctx,
unsigned char* der, long derSz)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_ASN1");
(void)pri;
if ((ctx == NULL) || (der == NULL)) {
ret = 0;
}
else {
ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSz,
WOLFSSL_FILETYPE_ASN1);
}
return ret;
}
#ifndef NO_RSA
*
* @param [in, out] ssl SSL object.
* @param [in] der Buffer holding DER encoded RSA private key.
* @param [in] derSz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1");
if ((ssl == NULL) || (der == NULL)) {
ret = 0;
}
else {
ret = wolfSSL_use_PrivateKey_buffer(ssl, der, derSz,
WOLFSSL_FILETYPE_ASN1);
}
return ret;
}
#endif
*
* @param [in, out] ssl SSL object.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate");
if ((ssl == NULL) || (x509 == NULL) || (x509->derCert == NULL)) {
ret = 0;
}
else {
long idx = 0;
ret = ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length,
WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0,
GET_VERIFY_SETTING_SSL(ssl));
}
return WS_RC(ret);
}
#endif
*
* @param [in, out] ssl SSL object.
* @param [in] der Buffer holding DER encoded certificate.
* @param [in] derSz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, const unsigned char* der,
int derSz)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1");
if ((ssl == NULL) || (der == NULL)) {
ret = 0;
}
else {
long idx = 0;
ret = ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
ssl, &idx, 0, GET_VERIFY_SETTING_SSL(ssl));
}
return WS_RC(ret);
}
#ifndef NO_FILESYSTEM
*
* @param [in, out] ssl SSL object.
* @param [in] file Name of file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
WOLFSSL_ABI
int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate_file");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 0, NULL,
GET_VERIFY_SETTING_SSL(ssl));
ret = WS_RC(ret);
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] file Name of file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
WOLFSSL_ABI
int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, ssl, 0, NULL,
GET_VERIFY_SETTING_SSL(ssl));
ret = WS_RC(ret);
}
return ret;
}
*
* Process up to MAX_CHAIN_DEPTH plus subject cert.
*
* @param [in, out] ssl SSL object.
* @param [in] file Name of file.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
WOLFSSL_ABI
int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, ssl,
1, NULL, GET_VERIFY_SETTING_SSL(ssl));
ret = WS_RC(ret);
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] file Name of file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file,
int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, NULL,
GET_VERIFY_SETTING_SSL(ssl));
ret = WS_RC(ret);
}
return ret;
}
#endif
#ifdef OPENSSL_EXTRA
#ifndef NO_FILESYSTEM
*
* @param [in, out] ctx SSL context object.
* @param [in] file Name of file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file,
int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey_file");
return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format);
}
*
* @param [in, out] ssl SSL object.
* @param [in] file Name of file.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format)
{
WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file");
return wolfSSL_use_PrivateKey_file(ssl, file, format);
}
#endif
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding certificate or private key.
* @param [in] sz Length of data in buffer in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @param [in] userChain Whether file contains chain of certificates.
* @param [in] flags Flags representing options for loading.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_load_verify_buffer_ex(WOLFSSL_CTX* ctx, const unsigned char* in,
long sz, int format, int userChain, word32 flags)
{
int ret;
int verify;
WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer_ex");
verify = GET_VERIFY_SETTING_CTX(ctx);
if (flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) {
verify = VERIFY_SKIP_DATE;
}
if (format == WOLFSSL_FILETYPE_PEM) {
ret = ProcessChainBuffer(ctx, NULL, in, sz, CA_TYPE, verify);
}
else {
ret = ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL, NULL,
userChain, verify);
}
#if defined(WOLFSSL_TRUST_PEER_CERT) && defined(OPENSSL_COMPATIBLE_DEFAULTS)
if (ret == 1) {
ret = wolfSSL_CTX_trust_peer_buffer(ctx, in, sz, format);
}
#endif
WOLFSSL_LEAVE("wolfSSL_CTX_load_verify_buffer_ex", ret);
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding certificate or private key.
* @param [in] sz Length of data in buffer in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
long sz, int format)
{
return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 0,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
}
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding certificate chain.
* @param [in] sz Length of data in buffer in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)
{
return wolfSSL_CTX_load_verify_buffer_ex(ctx, in, sz, format, 1,
WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS);
}
#ifdef WOLFSSL_TRUST_PEER_CERT
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding certificate/s.
* @param [in] sz Length of data in buffer in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ctx or in is NULL, or sz is less than zero.
*/
int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
long sz, int format)
{
int ret;
int verify;
WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer");
if ((ctx == NULL) || (in == NULL) || (sz < 0)) {
ret = BAD_FUNC_ARG;
}
else {
#if WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY
verify = VERIFY_SKIP_DATE;
#else
verify = GET_VERIFY_SETTING_CTX(ctx);
#endif
if (format == WOLFSSL_FILETYPE_PEM) {
ret = ProcessChainBuffer(ctx, NULL, in, sz, TRUSTED_PEER_TYPE,
verify);
}
else {
ret = ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, NULL,
NULL, 0, verify);
}
}
return ret;
}
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding certificate.
* @param [in] sz Size of data in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer");
ret = ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0,
GET_VERIFY_SETTING_CTX(ctx));
WOLFSSL_LEAVE("wolfSSL_CTX_use_certificate_buffer", ret);
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding private key.
* @param [in] sz Size of data in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx, const unsigned char* in,
long sz, int format)
{
int ret;
long consumed = 0;
WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer");
ret = ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL, &consumed,
0, GET_VERIFY_SETTING_CTX(ctx));
#ifdef WOLFSSL_DUAL_ALG_CERTS
if ((ret == 1) && (consumed < sz)) {
* buffer may contain both the primary and the alternative
* private key. Hence, we have to parse both of them.
*/
ret = ProcessBuffer(ctx, in + consumed, sz - consumed, format,
ALT_PRIVATEKEY_TYPE, NULL, NULL, 0, GET_VERIFY_SETTING_CTX(ctx));
}
#endif
(void)consumed;
WOLFSSL_LEAVE("wolfSSL_CTX_use_PrivateKey_buffer", ret);
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wolfSSL_CTX_use_AltPrivateKey_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_AltPrivateKey_buffer");
ret = ProcessBuffer(ctx, in, sz, format, ALT_PRIVATEKEY_TYPE, NULL,
NULL, 0, GET_VERIFY_SETTING_CTX(ctx));
WOLFSSL_LEAVE("wolfSSL_CTX_use_AltPrivateKey_buffer", ret);
return ret;
}
#endif
#ifdef WOLF_PRIVATE_KEY_ID
*
* @param [in, out] ctx SSL context object.
* @param [in] id Buffer holding id.
* @param [in] sz Size of data in bytes.
* @param [in] devId Device identifier.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_PrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId)
{
int ret = 1;
FreeDer(&ctx->privateKey);
if (AllocCopyDer(&ctx->privateKey, id, (word32)sz, PRIVATEKEY_TYPE,
ctx->heap) != 0) {
ret = 0;
}
if (ret == 1) {
ctx->privateKeyId = 1;
ctx->privateKeyLabel = 0;
if (devId != INVALID_DEVID) {
ctx->privateKeyDevId = devId;
}
else {
ctx->privateKeyDevId = ctx->devId;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
* afterwards. */
ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId);
#endif
}
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] id Buffer holding id.
* @param [in] sz Size of data in bytes.
* @param [in] devId Device identifier.
* @param [in] keySz Size of key.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId, long keySz)
{
int ret = wolfSSL_CTX_use_PrivateKey_Id(ctx, id, sz, devId);
if (ret == 1) {
ctx->privateKeySz = (int)keySz;
}
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] label Buffer holding label.
* @param [in] devId Device identifier.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_PrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
int devId)
{
int ret = 1;
word32 sz = (word32)XSTRLEN(label) + 1;
FreeDer(&ctx->privateKey);
if (AllocCopyDer(&ctx->privateKey, (const byte*)label, (word32)sz,
PRIVATEKEY_TYPE, ctx->heap) != 0) {
ret = 0;
}
if (ret == 1) {
ctx->privateKeyId = 0;
ctx->privateKeyLabel = 1;
if (devId != INVALID_DEVID) {
ctx->privateKeyDevId = devId;
}
else {
ctx->privateKeyDevId = ctx->devId;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
* afterwards. */
ret = wolfSSL_CTX_use_AltPrivateKey_Label(ctx, label, devId);
#endif
}
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wolfSSL_CTX_use_AltPrivateKey_Id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId)
{
int ret = 1;
if ((ctx == NULL) || (id == NULL)) {
ret = 0;
}
if (ret == 1) {
FreeDer(&ctx->altPrivateKey);
if (AllocDer(&ctx->altPrivateKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
ctx->heap) != 0) {
ret = 0;
}
}
if (ret == 1) {
XMEMCPY(ctx->altPrivateKey->buffer, id, sz);
ctx->altPrivateKeyId = 1;
if (devId != INVALID_DEVID) {
ctx->altPrivateKeyDevId = devId;
}
else {
ctx->altPrivateKeyDevId = ctx->devId;
}
}
return ret;
}
int wolfSSL_CTX_use_AltPrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id,
long sz, int devId, long keySz)
{
int ret = wolfSSL_CTX_use_AltPrivateKey_Id(ctx, id, sz, devId);
if (ret == 1) {
ctx->altPrivateKeySz = (word32)keySz;
}
return ret;
}
int wolfSSL_CTX_use_AltPrivateKey_Label(WOLFSSL_CTX* ctx, const char* label,
int devId)
{
int ret = 1;
word32 sz;
if ((ctx == NULL) || (label == NULL)) {
ret = 0;
}
if (ret == 1) {
sz = (word32)XSTRLEN(label) + 1;
FreeDer(&ctx->altPrivateKey);
if (AllocDer(&ctx->altPrivateKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
ctx->heap) != 0) {
ret = 0;
}
}
if (ret == 1) {
XMEMCPY(ctx->altPrivateKey->buffer, label, sz);
ctx->altPrivateKeyLabel = 1;
if (devId != INVALID_DEVID) {
ctx->altPrivateKeyDevId = devId;
}
else {
ctx->altPrivateKeyDevId = ctx->devId;
}
}
return ret;
}
#endif
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding DER encoded certificate chain.
* @param [in] sz Size of data in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz, int format)
{
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format");
return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1,
GET_VERIFY_SETTING_CTX(ctx));
}
*
* @param [in, out] ctx SSL context object.
* @param [in] in Buffer holding DER encoded certificate chain.
* @param [in] sz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx,
const unsigned char* in, long sz)
{
return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz,
WOLFSSL_FILETYPE_PEM);
}
*
* @param [in, out] ssl SSL object.
* @param [in] in Buffer holding user certificate.
* @param [in] sz Size of data in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, const unsigned char* in,
long sz, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate_buffer");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 0,
GET_VERIFY_SETTING_SSL(ssl));
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] in Buffer holding private key.
* @param [in] sz Size of data in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl, const unsigned char* in,
long sz, int format)
{
int ret;
long consumed = 0;
WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, ssl,
&consumed, 0, GET_VERIFY_SETTING_SSL(ssl));
#ifdef WOLFSSL_DUAL_ALG_CERTS
if ((ret == 1) && (consumed < sz)) {
* buffer may contain both the primary and the alternative
* private key. Hence, we have to parse both of them.
*/
ret = ProcessBuffer(ssl->ctx, in + consumed, sz - consumed, format,
ALT_PRIVATEKEY_TYPE, ssl, NULL, 0, GET_VERIFY_SETTING_SSL(ssl));
}
#endif
}
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wolfSSL_use_AltPrivateKey_buffer(WOLFSSL* ssl, const unsigned char* in,
long sz, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_AltPrivateKey_buffer");
ret = ProcessBuffer(ssl->ctx, in, sz, format, ALT_PRIVATEKEY_TYPE, ssl,
NULL, 0, GET_VERIFY_SETTING_SSL(ssl));
WOLFSSL_LEAVE("wolfSSL_use_AltPrivateKey_buffer", ret);
return ret;
}
#endif
#ifdef WOLF_PRIVATE_KEY_ID
*
* @param [in, out] ssl SSL object.
* @param [in] id Buffer holding id.
* @param [in] sz Size of data in bytes.
* @param [in] devId Device identifier.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_PrivateKey_Id(WOLFSSL* ssl, const unsigned char* id,
long sz, int devId)
{
int ret = 1;
if (ssl->buffers.weOwnKey) {
FreeDer(&ssl->buffers.key);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.keyMask);
#endif
}
if (AllocCopyDer(&ssl->buffers.key, id, (word32)sz, PRIVATEKEY_TYPE,
ssl->heap) != 0) {
ret = 0;
}
if (ret == 1) {
ssl->buffers.weOwnKey = 1;
ssl->buffers.keyId = 1;
ssl->buffers.keyLabel = 0;
if (devId != INVALID_DEVID) {
ssl->buffers.keyDevId = devId;
}
else {
ssl->buffers.keyDevId = ssl->devId;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
* afterwards. */
ret = wolfSSL_use_AltPrivateKey_Id(ssl, id, sz, devId);
#endif
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] id Buffer holding id.
* @param [in] sz Size of data in bytes.
* @param [in] devId Device identifier.
* @param [in] keySz Size of key.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id,
long sz, int devId, long keySz)
{
int ret = wolfSSL_use_PrivateKey_Id(ssl, id, sz, devId);
if (ret == 1) {
ssl->buffers.keySz = (int)keySz;
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] label Buffer holding label.
* @param [in] devId Device identifier.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_use_PrivateKey_Label(WOLFSSL* ssl, const char* label, int devId)
{
int ret = 1;
word32 sz = (word32)XSTRLEN(label) + 1;
if (ssl->buffers.weOwnKey) {
FreeDer(&ssl->buffers.key);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.keyMask);
#endif
}
if (AllocCopyDer(&ssl->buffers.key, (const byte*)label, (word32)sz,
PRIVATEKEY_TYPE, ssl->heap) != 0) {
ret = 0;
}
if (ret == 1) {
ssl->buffers.weOwnKey = 1;
ssl->buffers.keyId = 0;
ssl->buffers.keyLabel = 1;
if (devId != INVALID_DEVID) {
ssl->buffers.keyDevId = devId;
}
else {
ssl->buffers.keyDevId = ssl->devId;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
* that afterwards. */
ret = wolfSSL_use_AltPrivateKey_Label(ssl, label, devId);
#endif
}
return ret;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
int wolfSSL_use_AltPrivateKey_Id(WOLFSSL* ssl, const unsigned char* id, long sz,
int devId)
{
int ret = 1;
if ((ssl == NULL) || (id == NULL)) {
ret = 0;
}
if (ret == 1) {
if (ssl->buffers.weOwnAltKey) {
FreeDer(&ssl->buffers.altKey);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.altKeyMask);
#endif
}
if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
ssl->heap) == 0) {
ret = 0;
}
}
if (ret == 1) {
XMEMCPY(ssl->buffers.altKey->buffer, id, sz);
ssl->buffers.weOwnAltKey = 1;
ssl->buffers.altKeyId = 1;
if (devId != INVALID_DEVID) {
ssl->buffers.altKeyDevId = devId;
}
else {
ssl->buffers.altKeyDevId = ssl->devId;
}
}
return ret;
}
int wolfSSL_use_AltPrivateKey_id(WOLFSSL* ssl, const unsigned char* id, long sz,
int devId, long keySz)
{
int ret = wolfSSL_use_AltPrivateKey_Id(ssl, id, sz, devId);
if (ret == 1) {
ssl->buffers.altKeySz = (word32)keySz;
}
return ret;
}
int wolfSSL_use_AltPrivateKey_Label(WOLFSSL* ssl, const char* label, int devId)
{
int ret = 1;
word32 sz;
if ((ssl == NULL) || (label == NULL)) {
ret = 0;
}
if (ret == 1) {
sz = (word32)XSTRLEN(label) + 1;
if (ssl->buffers.weOwnAltKey) {
FreeDer(&ssl->buffers.altKey);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.altKeyMask);
#endif
}
if (AllocDer(&ssl->buffers.altKey, (word32)sz, ALT_PRIVATEKEY_TYPE,
ssl->heap) == 0) {
ret = 0;
}
}
if (ret == 1) {
XMEMCPY(ssl->buffers.altKey->buffer, label, sz);
ssl->buffers.weOwnAltKey = 1;
ssl->buffers.altKeyLabel = 1;
if (devId != INVALID_DEVID) {
ssl->buffers.altKeyDevId = devId;
}
else {
ssl->buffers.altKeyDevId = ssl->devId;
}
}
return ret;
}
#endif
#endif
*
* @param [in, out] ssl SSL object.
* @param [in] in Buffer holding DER encoded certificate chain.
* @param [in] sz Size of data in bytes.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ssl is NULL.
*/
int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl,
const unsigned char* in, long sz, int format)
{
int ret;
WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, ssl, NULL, 1,
GET_VERIFY_SETTING_SSL(ssl));
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] in Buffer holding DER encoded certificate chain.
* @param [in] sz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
* @return Negative on error.
*/
int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, const unsigned char* in,
long sz)
{
return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz,
WOLFSSL_FILETYPE_PEM);
}
#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
defined(WOLFSSL_HAPROXY)
*
* @param [in, out] chain Buffer holding encoded certificate for TLS.
* @param [in] weOwn Indicates we need to free chain if repleced.
* @param [in] cert Buffer holding DER encoded certificate.
* @param [in] certSz Size of DER encoded certificate in bytes.
* @param [in] heap Dynamic memory allocation hint.
* @return 1 on success.
* @return 0 on failure.
*/
static int wolfssl_add_to_chain(DerBuffer** chain, int weOwn, const byte* cert,
word32 certSz, void* heap)
{
int res = 1;
int ret;
DerBuffer* oldChain = *chain;
DerBuffer* newChain = NULL;
word32 len = 0;
if (oldChain != NULL) {
len = oldChain->length;
}
ret = AllocDer(&newChain, len + CERT_HEADER_SZ + certSz, CERT_TYPE, heap);
if (ret != 0) {
WOLFSSL_MSG("AllocDer error");
res = 0;
}
if (res == 1) {
if (oldChain != NULL) {
XMEMCPY(newChain->buffer, oldChain->buffer, len);
}
c32to24(certSz, newChain->buffer + len);
XMEMCPY(newChain->buffer + len + CERT_HEADER_SZ, cert, certSz);
if (weOwn) {
FreeDer(chain);
}
*chain = newChain;
}
return res;
}
#endif
#ifdef OPENSSL_EXTRA
*
* @param [in, out] ctx SSL context.
* @param [in] der Buffer holding DER encoded certificate.
* @param [in] derSz Size of data in buffer.
* @return 1 on success.
* @return 0 on failure.
*/
static int wolfssl_ctx_add_to_chain(WOLFSSL_CTX* ctx, const byte* der,
int derSz)
{
int res = 1;
int ret;
DerBuffer* derBuffer = NULL;
ret = AllocCopyDer(&derBuffer, der, (word32)derSz, CERT_TYPE, ctx->heap);
if (ret != 0) {
WOLFSSL_MSG("Memory Error");
res = 0;
}
if (res == 1) {
res = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA,
GET_VERIFY_SETTING_CTX(ctx));
if (res != 1) {
res = 0;
}
}
if (res == 1) {
res = wolfssl_add_to_chain(&ctx->certChain, 1, der, (word32)derSz, ctx->heap);
#ifdef WOLFSSL_TLS13
ctx->certChainCnt++;
#endif
}
return res;
}
*
* @param [in, out] ctx SSL context.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
{
int ret = 1;
int derSz = 0;
const byte* der = NULL;
WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert");
if ((ctx == NULL) || (x509 == NULL)) {
WOLFSSL_MSG("Bad Argument");
ret = 0;
}
if (ret == 1) {
der = wolfSSL_X509_get_der(x509, &derSz);
if ((der == NULL) || (derSz <= 0)) {
WOLFSSL_MSG("Error getting X509 DER");
ret = 0;
}
}
if ((ret == 1) && (ctx->certificate == NULL)) {
WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format");
ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE,
NULL, NULL, 1, GET_VERIFY_SETTING_CTX(ctx));
if (ret != 1) {
ret = 0;
}
}
else if (ret == 1) {
ret = wolfssl_ctx_add_to_chain(ctx, der, derSz);
}
if (ret == 1) {
wolfSSL_X509_free(x509);
}
WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret);
return ret;
}
#endif
#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \
defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \
defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \
defined(WOLFSSL_HAPROXY)
*
* @param [in, out] ctx SSL context object.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x)
{
int res = 1;
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate");
if ((ctx == NULL) || (x == NULL) || (x->derCert == NULL)) {
WOLFSSL_MSG("Bad parameter");
res = 0;
}
if (res == 1) {
FreeDer(&ctx->certificate);
ret = AllocCopyDer(&ctx->certificate, x->derCert->buffer,
x->derCert->length, CERT_TYPE, ctx->heap);
if (ret != 0) {
res = 0;
}
}
#ifdef KEEP_OUR_CERT
if (res == 1) {
if ((ctx->ourCert != NULL) && ctx->ownOurCert) {
wolfSSL_X509_free(ctx->ourCert);
}
#ifndef WOLFSSL_X509_STORE_CERTS
ctx->ourCert = x;
if (wolfSSL_X509_up_ref(x) != 1) {
res = 0;
}
#else
ctx->ourCert = wolfSSL_X509_d2i_ex(NULL, x->derCert->buffer,
x->derCert->length, ctx->heap);
if (ctx->ourCert == NULL) {
res = 0;
}
#endif
ctx->ownOurCert = 1;
}
#endif
if (res == 1) {
wolfssl_set_have_from_key_oid(ctx, NULL, x->pubKeyOID);
}
return res;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_add0_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_add0_chain_cert");
ret = wolfSSL_CTX_add1_chain_cert(ctx, x509);
if (ret == 1) {
wolfSSL_X509_free(x509);
}
return ret;
}
*
* X509 object copied or up referenced.
*
* @param [in, out] ctx SSL context object.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_add1_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CTX_add1_chain_cert");
if ((ctx == NULL) || (x509 == NULL) || (x509->derCert == NULL)) {
ret = 0;
}
if ((ret == 1) && (ctx->certificate == NULL)) {
ret = wolfSSL_CTX_use_certificate(ctx, x509);
}
else if ((ret == 1) && ((ret = wolfSSL_X509_up_ref(x509)) == 1)) {
ret = wolfSSL_CTX_load_verify_buffer(ctx, x509->derCert->buffer,
x509->derCert->length, WOLFSSL_FILETYPE_ASN1);
if (ret == 1) {
ret = wolfssl_add_to_chain(&ctx->certChain, 1,
x509->derCert->buffer, x509->derCert->length, ctx->heap);
}
if ((ret == 1) && (ctx->x509Chain == NULL)) {
ctx->x509Chain = wolfSSL_sk_X509_new_null();
if (ctx->x509Chain == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_new_null error");
ret = 0;
}
}
if (ret == 1) {
ret = wolfSSL_sk_X509_push(ctx->x509Chain, x509);
}
if (ret != 1) {
wolfSSL_X509_free(x509);
}
}
return WS_RC(ret);
}
#ifdef KEEP_OUR_CERT
*
* @param [in, out] ssl SSL object.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_add0_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_add0_chain_cert");
if ((ssl == NULL) || (ssl->ctx == NULL) || (x509 == NULL) ||
(x509->derCert == NULL)) {
ret = 0;
}
if ((ret == 1) && (ssl->buffers.certificate == NULL)) {
ret = wolfSSL_use_certificate(ssl, x509);
if (ret == 1) {
if (ssl->buffers.weOwnCert) {
wolfSSL_X509_free(ssl->ourCert);
}
ssl->ourCert = x509;
ssl->buffers.weOwnCert = 1;
}
}
else if (ret == 1) {
ret = wolfssl_add_to_chain(&ssl->buffers.certChain,
ssl->buffers.weOwnCertChain, x509->derCert->buffer,
x509->derCert->length, ssl->heap);
if (ret == 1) {
ssl->buffers.weOwnCertChain = 1;
if (ssl->ourCertChain == NULL) {
ssl->ourCertChain = wolfSSL_sk_X509_new_null();
if (ssl->ourCertChain == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_new_null error");
ret = 0;
}
}
}
if (ret == 1) {
ret = wolfSSL_sk_X509_push(ssl->ourCertChain, x509);
if (ret != 1) {
wolfSSL_X509_free(x509);
}
}
}
return WS_RC(ret);
}
*
* X509 object is up referenced.
*
* @param [in, out] ssl SSL object.
* @param [in] x509 X509 certificate object.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_add1_chain_cert(WOLFSSL* ssl, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_add1_chain_cert");
if ((ssl == NULL) || (ssl->ctx == NULL) || (x509 == NULL) ||
(x509->derCert == NULL)) {
ret = 0;
}
if ((ret == 1) && ((ret == wolfSSL_X509_up_ref(x509)) == 1)) {
if ((ret = wolfSSL_add0_chain_cert(ssl, x509)) != 1) {
wolfSSL_X509_free(x509);
}
}
return ret;
}
#endif
#endif
WOLFSSL_NGINX, HAVE_POCO_LIB, WOLFSSL_HAPROXY */
#ifdef OPENSSL_EXTRA
*
* @param [in, out] ctx SSL context object.
* @param [in] pkey EVP private key.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey");
if ((ctx == NULL) || (pkey == NULL) || (pkey->pkey.ptr == NULL)) {
ret = 0;
}
if (ret == 1) {
switch (pkey->type) {
#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)
case EVP_PKEY_RSA:
WOLFSSL_MSG("populating RSA key");
ret = PopulateRSAEvpPkeyDer(pkey);
break;
#endif
#if !defined(HAVE_SELFTEST) && (defined(WOLFSSL_KEY_GEN) || \
defined(WOLFSSL_CERT_GEN)) && !defined(NO_DSA)
case EVP_PKEY_DSA:
break;
#endif
* !NO_DSA */
#ifdef HAVE_ECC
case EVP_PKEY_EC:
WOLFSSL_MSG("populating ECC key");
ret = ECC_populate_EVP_PKEY(pkey, pkey->ecc);
break;
#endif
default:
ret = 0;
}
}
if (ret == 1) {
ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx,
(const unsigned char*)pkey->pkey.ptr, pkey->pkey_sz,
SSL_FILETYPE_ASN1);
}
return ret;
}
#endif
#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) || \
defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_QT)
*
* @param [in, out] ctx SSL context object.
* @param [in] der Buffer holding DER encoded certificate.
* @param [in] derSz Size of data in bytes.
* @return 1 on success.
* @return 0 on failure.
*/
int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz,
const unsigned char *der)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1");
if ((ctx == NULL) || (der == NULL)) {
ret = 0;
}
if ((ret == 1) && (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz,
WOLFSSL_FILETYPE_ASN1) != 1)) {
ret = 0;
}
return ret;
}
#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)
*
* @param [in, out] ctx SSL context object.
* @param [in] rsa RSA private key.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ctx or rsa is NULL.
* @return MEMORY_E when dynamic memory allocation fails.
*/
int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa)
{
int ret = 1;
int derSize;
unsigned char* der = NULL;
unsigned char* p;
WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey");
if ((ctx == NULL) || (rsa == NULL)) {
WOLFSSL_MSG("one or more inputs were NULL");
ret = BAD_FUNC_ARG;
}
if ((ret == 1) && ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, NULL)) <= 0)) {
ret = 0;
}
if (ret == 1) {
der = (unsigned char*)XMALLOC(derSize, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL) {
WOLFSSL_MSG("Malloc failure");
ret = MEMORY_E;
}
}
if (ret == 1) {
p = der;
if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &p)) <= 0) {
WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure");
ret = 0;
}
}
if (ret == 1) {
ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, der, derSize,
SSL_FILETYPE_ASN1);
if (ret != WOLFSSL_SUCCESS) {
WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure");
ret = 0;
}
}
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
#endif
#endif
#endif
#ifdef OPENSSL_EXTRA
*
* This is an OpenSSL compatibility layer function, but it doesn't mirror
* the exact functionality of its OpenSSL counterpart. We don't support the
* notion of an "OpenSSL directory". This function will attempt to load the
* environment variables SSL_CERT_DIR and SSL_CERT_FILE, if either are
* found, they will be loaded. Otherwise, it will act as a wrapper around
* our native wolfSSL_CTX_load_system_CA_certs function. This function does
* conform to OpenSSL's return value conventions.
*
* @param [in] ctx SSL context object.
* @return 1 on success.
* @return 0 on failure.
* @return WOLFSSL_FATAL_ERROR when using a filesystem is not supported.
*/
int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx)
{
int ret;
#ifdef XGETENV
char* certDir;
char* certFile;
word32 flags;
#elif !defined(WOLFSSL_SYS_CA_CERTS)
(void)ctx;
#endif
WOLFSSL_ENTER("wolfSSL_CTX_set_default_verify_paths");
#ifdef XGETENV
certDir = XGETENV("SSL_CERT_DIR");
certFile = XGETENV("SSL_CERT_FILE");
flags = WOLFSSL_LOAD_FLAG_PEM_CA_ONLY;
if ((certDir != NULL) || (certFile != NULL)) {
if (certDir != NULL) {
* the directory is bad and can't be used (e.g. if one is
* expired), so we use WOLFSSL_LOAD_FLAG_IGNORE_ERR.
*/
flags |= WOLFSSL_LOAD_FLAG_IGNORE_ERR;
}
ret = wolfSSL_CTX_load_verify_locations_ex(ctx, certFile, certDir,
flags);
if (ret != 1) {
WOLFSSL_MSG_EX("Failed to load CA certs from SSL_CERT_FILE: %s"
" SSL_CERT_DIR: %s. Error: %d", certFile,
certDir, ret);
ret = 0;
}
}
else
#endif
{
#ifdef NO_FILESYSTEM
WOLFSSL_MSG("wolfSSL_CTX_set_default_verify_paths not supported"
" with NO_FILESYSTEM enabled");
ret = WOLFSSL_FATAL_ERROR;
#elif defined(WOLFSSL_SYS_CA_CERTS)
ret = wolfSSL_CTX_load_system_CA_certs(ctx);
if (ret == WOLFSSL_BAD_PATH) {
* failure. We do the same here.
*/
ret = 1;
}
#else
system CA cert directory. Allow skipping this without erroring out. */
ret = 1;
#endif
}
WOLFSSL_LEAVE("wolfSSL_CTX_set_default_verify_paths", ret);
return ret;
}
#endif
#ifndef NO_DH
*
* @param [in, out] ssl SSL object.
* @param [in] p Buffer holding prime.
* @param [in] pSz Length of prime in bytes.
* @param [in] g Buffer holding generator.
* @param [in] gSz Length of generator in bytes.
* @return 1 on success.
* @return 0 on failure.
* @return DH_KEY_SIZE_E when the prime is too short or long.
* @return SIDE_ERROR when the SSL is for a client.
*/
static int wolfssl_set_tmp_dh(WOLFSSL* ssl, unsigned char* p, int pSz,
unsigned char* g, int gSz)
{
int ret = 1;
if (((word16)pSz < ssl->options.minDhKeySz) ||
((word16)pSz > ssl->options.maxDhKeySz)) {
ret = DH_KEY_SIZE_E;
}
if ((ret == 1) && (ssl->options.side == WOLFSSL_CLIENT_END)) {
ret = SIDE_ERROR;
}
if (ret == 1) {
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
ssl->options.dhKeyTested = 0;
ssl->options.dhDoKeyTest = 1;
#endif
if (ssl->buffers.weOwnDH) {
XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
}
ssl->buffers.serverDH_P.buffer = p;
ssl->buffers.serverDH_G.buffer = g;
ssl->buffers.serverDH_P.length = (unsigned int)pSz;
ssl->buffers.serverDH_G.length = (unsigned int)gSz;
ssl->buffers.weOwnDH = 1;
ssl->options.haveDH = 1;
}
if ((ret == 1) && (AllocateSuites(ssl) != 0)) {
ssl->buffers.serverDH_P.buffer = NULL;
ssl->buffers.serverDH_G.buffer = NULL;
ret = 0;
}
if (ret == 1) {
InitSuites(ssl->suites, ssl->version, SSL_KEY_SZ(ssl),
WOLFSSL_HAVE_RSA, SSL_HAVE_PSK(ssl), ssl->options.haveDH,
ssl->options.haveECDSAsig, ssl->options.haveECC, TRUE,
ssl->options.haveStaticECC, ssl->options.haveFalconSig,
ssl->options.haveDilithiumSig, ssl->options.useAnon, TRUE,
ssl->options.side);
}
return ret;
}
*
* @param [in, out] ssl SSL object.
* @param [in] p Buffer holding prime.
* @param [in] pSz Length of prime in bytes.
* @param [in] g Buffer holding generator.
* @param [in] gSz Length of generator in bytes.
* @return 1 on success.
* @return 0 on failure.
* @return DH_KEY_SIZE_E when the prime is too short or long.
* @return SIDE_ERROR when the SSL is for a client.
* @return MEMORY_E when dynamic memory allocation fails.
*/
int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
const unsigned char* g, int gSz)
{
int ret = 1;
byte* pAlloc = NULL;
byte* gAlloc = NULL;
WOLFSSL_ENTER("wolfSSL_SetTmpDH");
if ((ssl == NULL) || (p == NULL) || (g == NULL)) {
ret = 0;
}
if (ret == 1) {
pAlloc = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
gAlloc = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if ((pAlloc == NULL) || (gAlloc == NULL)) {
ret = MEMORY_E;
}
}
if (ret == 1) {
XMEMCPY(pAlloc, p, pSz);
XMEMCPY(gAlloc, g, gSz);
ret = wolfssl_set_tmp_dh(ssl, pAlloc, pSz, gAlloc, gSz);
}
if (ret != 1 && ssl != NULL) {
XFREE(pAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(gAlloc, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
WOLFSSL_LEAVE("wolfSSL_SetTmpDH", ret);
return ret;
}
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
*
* @param [in] p Buffer holding prime.
* @param [in] pSz Length of prime in bytes.
* @param [in] g Buffer holding generator.
* @param [in] gSz Length of generator in bytes.
* @return 1 on success.
* @return DH_CHECK_PUB_E when p is not a prime.
* @return BAD_FUNC_ARG when p or g is NULL, or pSz or gSz is 0.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int wolfssl_check_dh_key(unsigned char* p, int pSz, unsigned char* g,
int gSz)
{
WC_RNG rng;
int ret = 0;
#ifndef WOLFSSL_SMALL_STACK
DhKey checkKey[1];
#else
DhKey *checkKey;
#endif
#ifdef WOLFSSL_SMALL_STACK
checkKey = (DhKey*)XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH);
if (checkKey == NULL) {
ret = MEMORY_E;
}
#endif
if ((ret == 0) && ((ret = wc_InitRng(&rng)) == 0)) {
if ((ret = wc_InitDhKey(checkKey)) == 0) {
ret = wc_DhSetCheckKey(checkKey, p, (word32)pSz, g, gSz, NULL, 0, 0, &rng);
wc_FreeDhKey(checkKey);
}
wc_FreeRng(&rng);
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(checkKey, NULL, DYNAMIC_TYPE_DH);
#endif
return WC_TO_WS_RC(ret);
}
#endif
*
* @param [in, out] ctx SSL context object.
* @param [in] p Buffer holding prime.
* @param [in] pSz Length of prime in bytes.
* @param [in] g Buffer holding generator.
* @param [in] gSz Length of generator in bytes.
* @return 1 on success.
* @return 0 on failure.
* @return DH_KEY_SIZE_E when the prime is too short or long.
* @return SIDE_ERROR when the SSL is for a client.
* @return BAD_FUNC_ARG when ctx, p or g is NULL.
* @return DH_CHECK_PUB_E when p is not a prime.
* @return MEMORY_E when dynamic memory allocation fails.
*/
static int wolfssl_ctx_set_tmp_dh(WOLFSSL_CTX* ctx, unsigned char* p, int pSz,
unsigned char* g, int gSz)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH");
if (((word16)pSz < ctx->minDhKeySz) || ((word16)pSz > ctx->maxDhKeySz)) {
ret = DH_KEY_SIZE_E;
}
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
if (ret == 1) {
ret = wolfssl_check_dh_key(p, pSz, g, gSz);
ctx->dhKeyTested = (ret == 1);
}
#endif
if (ret == 1) {
XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ctx->serverDH_P.buffer = p;
ctx->serverDH_G.buffer = g;
ctx->serverDH_P.length = (unsigned int)pSz;
ctx->serverDH_G.length = (unsigned int)gSz;
ctx->haveDH = 1;
}
WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0);
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] p Buffer holding prime.
* @param [in] pSz Length of prime in bytes.
* @param [in] g Buffer holding generator.
* @param [in] gSz Length of generator in bytes.
* @return 1 on success.
* @return 0 on failure.
* @return DH_KEY_SIZE_E when the prime is too short or long.
* @return SIDE_ERROR when the SSL is for a client.
* @return BAD_FUNC_ARG when ctx, p or g is NULL.
* @return DH_CHECK_PUB_E when p is not a prime.
*/
int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
const unsigned char* g, int gSz)
{
int ret = 1;
byte* pAlloc = NULL;
byte* gAlloc = NULL;
if ((ctx == NULL) || (p == NULL) || (g == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 1) {
pAlloc = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
gAlloc = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if ((pAlloc == NULL) || (gAlloc == NULL)) {
XFREE(pAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
pAlloc = NULL;
XFREE(gAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
gAlloc = NULL;
ret = MEMORY_E;
}
}
if (ret == 1) {
XMEMCPY(pAlloc, p, pSz);
XMEMCPY(gAlloc, g, gSz);
ret = wolfssl_ctx_set_tmp_dh(ctx, pAlloc, pSz, gAlloc, gSz);
}
if (ret != 1) {
if (pAlloc)
XFREE(pAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if (gAlloc)
XFREE(gAlloc, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
return ret;
}
#ifdef OPENSSL_EXTRA
*
* @param [in, out] ssl SSL object.
* @param [in] dh DH object.
* @return 1 on success.
* @return 0 on failure.
* @return WOLFSSL_FATAL_ERROR on failure.
* @return BAD_FUNC_ARG when ssl or dh is NULL.
* @return DH_KEY_SIZE_E when the prime is too short or long.
* @return SIDE_ERROR when the SSL is for a client.
*/
long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh)
{
int ret = 1;
byte* p = NULL;
byte* g = NULL;
int pSz = 0;
int gSz = 0;
WOLFSSL_ENTER("wolfSSL_set_tmp_dh");
if ((ssl == NULL) || (dh == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 1) {
pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
if ((pSz <= 0) || (gSz <= 0)) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if ((p == NULL) || (g == NULL)) {
ret = MEMORY_E;
}
}
if (ret == 1) {
pSz = wolfSSL_BN_bn2bin(dh->p, p);
gSz = wolfSSL_BN_bn2bin(dh->g, g);
if ((pSz <= 0) || (gSz <= 0)) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
ret = wolfssl_set_tmp_dh(ssl, p, pSz, g, gSz);
}
if (ret != 1 && ssl != NULL) {
XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
return ret;
}
*
* @param [in, out] ctx SSL context object.
* @param [in] dh DH object.
* @return 1 on success.
* @return 0 on failure.
* @return DH_KEY_SIZE_E when the prime is too short or long.
* @return SIDE_ERROR when the SSL is for a client.
* @return BAD_FUNC_ARG when ctx, p or g is NULL.
* @return DH_CHECK_PUB_E when p is not a prime.
*/
long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh)
{
int ret = 1;
int pSz = 0;
int gSz = 0;
byte* p = NULL;
byte* g = NULL;
WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh");
if ((ctx == NULL) || (dh == NULL)) {
ret = BAD_FUNC_ARG;
}
if (ret == 1) {
pSz = wolfSSL_BN_bn2bin(dh->p, NULL);
gSz = wolfSSL_BN_bn2bin(dh->g, NULL);
if ((pSz <= 0) || (gSz <= 0)) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
if ((p == NULL) || (g == NULL)) {
ret = MEMORY_E;
}
}
if (ret == 1) {
pSz = wolfSSL_BN_bn2bin(dh->p, p);
gSz = wolfSSL_BN_bn2bin(dh->g, g);
if ((pSz < 0) && (gSz < 0)) {
ret = WOLFSSL_FATAL_ERROR;
}
}
if (ret == 1) {
ret = wolfssl_ctx_set_tmp_dh(ctx, p, pSz, g, gSz);
}
if (ret != 1 && ctx != NULL) {
XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
return ret;
}
#endif
#ifndef NO_CERTS
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] buf Buffer holding encoded DH parameters.
* @param [in] sz Size of encoded DH parameters.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return 0 on failure.
* @return BAD_FUNC_ARG when ctx and ssl NULL or buf is NULL.
* @return NOT_COMPLED_IN when format is PEM but PEM is not supported.
* @return WOLFSSL_BAD_FILETYPE if format is not supported.
*/
static int ws_ctx_ssl_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const unsigned char* buf, long sz, int format)
{
DerBuffer* der = NULL;
int res = 1;
int ret;
word32 pSz = MAX_DH_SIZE;
word32 gSz = MAX_DH_SIZE;
byte* p = NULL;
byte* g = NULL;
void* heap = WOLFSSL_HEAP(ctx, ssl);
if (((ctx == NULL) && (ssl == NULL)) || (buf == NULL)) {
res = BAD_FUNC_ARG;
}
if ((res == 1) && (format != WOLFSSL_FILETYPE_ASN1)) {
if (format != WOLFSSL_FILETYPE_PEM) {
res = WOLFSSL_BAD_FILETYPE;
}
#ifndef WOLFSSL_PEM_TO_DER
else {
res = NOT_COMPILED_IN;
}
#endif
}
if ((res == 1) && (format != WOLFSSL_FILETYPE_PEM)) {
ret = AllocDer(&der, 0, DH_PARAM_TYPE, heap);
if (ret == 0) {
der->buffer = (byte*)buf;
der->length = (word32)sz;
}
else {
res = ret;
}
}
if (res == 1) {
p = (byte*)XMALLOC(pSz, heap, DYNAMIC_TYPE_PUBLIC_KEY);
g = (byte*)XMALLOC(gSz, heap, DYNAMIC_TYPE_PUBLIC_KEY);
if ((p == NULL) || (g == NULL)) {
res = MEMORY_E;
}
}
#ifdef WOLFSSL_PEM_TO_DER
if ((res == 1) && (format == WOLFSSL_FILETYPE_PEM)) {
ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, heap, NULL, NULL);
if (ret < 0) {
ret = PemToDer(buf, sz, X942_PARAM_TYPE, &der, heap, NULL, NULL);
}
#if defined(WOLFSSL_WPAS) && !defined(NO_DSA)
if (ret < 0) {
ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, heap, NULL, NULL);
}
#endif
if (ret < 0) {
res = ret;
}
}
#endif
if (res == 1) {
if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) {
res = WOLFSSL_BAD_FILETYPE;
}
else if (ssl != NULL) {
res = wolfssl_set_tmp_dh(ssl, p, (int)pSz, g, gSz);
}
else {
res = wolfssl_ctx_set_tmp_dh(ctx, p, (int)pSz, g, gSz);
}
}
FreeDer(&der);
if (res != 1) {
XFREE(p, heap, DYNAMIC_TYPE_PUBLIC_KEY);
XFREE(g, heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
return res;
}
*
* @param [in, out] ssl SSL object.
* @param [in] buf Buffer holding encoded DH parameters.
* @param [in] sz Size of encoded DH parameters.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return BAD_FUNC_ARG when ssl or buf is NULL.
* @return NOT_COMPLED_IN when format is PEM but PEM is not supported.
* @return WOLFSSL_BAD_FILETYPE if format is not supported.
*/
int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz,
int format)
{
return ws_ctx_ssl_set_tmp_dh(NULL, ssl, buf, sz, format);
}
*
* @param [in, out] ctx SSL context object.
* @param [in] buf Buffer holding encoded DH parameters.
* @param [in] sz Size of encoded DH parameters.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return BAD_FUNC_ARG when ctx or buf is NULL.
* @return NOT_COMPLED_IN when format is PEM but PEM is not supported.
* @return WOLFSSL_BAD_FILETYPE if format is not supported.
*/
int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf,
long sz, int format)
{
return ws_ctx_ssl_set_tmp_dh(ctx, NULL, buf, sz, format);
}
#ifndef NO_FILESYSTEM
*
* @param [in, out] ctx SSL context object.
* @param [in, out] ssl SSL object.
* @param [in] fname Name of file to load.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return BAD_FUNC_ARG when ctx and ssl NULL or fname is NULL.
* @return NOT_COMPLED_IN when format is PEM but PEM is not supported.
* @return WOLFSSL_BAD_FILETYPE if format is not supported.
*/
static int ws_ctx_ssl_set_tmp_dh_file(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
const char* fname, int format)
{
int res = 1;
int ret;
#ifndef WOLFSSL_SMALL_STACK
byte stackBuffer[FILE_BUFFER_SIZE];
#endif
StaticBuffer dhFile;
long sz = 0;
void* heap = WOLFSSL_HEAP(ctx, ssl);
#ifdef WOLFSSL_SMALL_STACK
static_buffer_init(&dhFile);
#else
static_buffer_init(&dhFile, stackBuffer, FILE_BUFFER_SIZE);
#endif
if (((ctx == NULL) && (ssl == NULL)) || (fname == NULL)) {
res = BAD_FUNC_ARG;
}
if (res == 1) {
ret = wolfssl_read_file_static(fname, &dhFile, heap, DYNAMIC_TYPE_FILE,
&sz);
if (ret != 0) {
res = ret;
}
}
if (res == 1) {
if (ssl != NULL) {
res = wolfSSL_SetTmpDH_buffer(ssl, dhFile.buffer, sz, format);
}
else {
res = wolfSSL_CTX_SetTmpDH_buffer(ctx, dhFile.buffer, sz, format);
}
}
static_buffer_free(&dhFile, heap, DYNAMIC_TYPE_FILE);
return res;
}
*
* @param [in, out] ssl SSL object.
* @param [in] fname Name of file to load.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return BAD_FUNC_ARG when ssl or fname is NULL.
* @return NOT_COMPLED_IN when format is PEM but PEM is not supported.
* @return WOLFSSL_BAD_FILETYPE if format is not supported.
*/
int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format)
{
return ws_ctx_ssl_set_tmp_dh_file(NULL, ssl, fname, format);
}
*
* @param [in, out] ctx SSL context object.
* @param [in] fname Name of file to load.
* @param [in] format Format of data:
* WOLFSSL_FILETYPE_PEM or WOLFSSL_FILETYPE_ASN1.
* @return 1 on success.
* @return BAD_FUNC_ARG when ctx or fname is NULL.
* @return NOT_COMPLED_IN when format is PEM but PEM is not supported.
* @return WOLFSSL_BAD_FILETYPE if format is not supported.
*/
int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format)
{
return ws_ctx_ssl_set_tmp_dh_file(ctx, NULL, fname, format);
}
#endif
#endif
#endif
#endif