#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#if !defined(WOLFSSL_SSL_API_CERT_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
#warning ssl_api_cert.c is not compiled separately from ssl.c
#endif
#else
#ifndef NO_CERTS
int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req)
{
if (ctx == NULL)
return BAD_FUNC_ARG;
if (ctx->method->side != WOLFSSL_SERVER_END)
return SIDE_ERROR;
ctx->mutualAuth = (byte)req;
return 0;
}
int wolfSSL_mutual_auth(WOLFSSL* ssl, int req)
{
if (ssl == NULL)
return BAD_FUNC_ARG;
if (ssl->options.side != WOLFSSL_SERVER_END)
return SIDE_ERROR;
ssl->options.mutualAuth = (word16)req;
return 0;
}
WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx)
{
WOLFSSL_CERT_MANAGER* cm = NULL;
if (ctx)
cm = ctx->cm;
return cm;
}
void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth");
if ((ctx == NULL) || (depth < 0) || (depth > MAX_CHAIN_DEPTH)) {
WOLFSSL_MSG("Bad depth argument, too large or less than 0");
}
else {
ctx->verifyDepth = (byte)depth;
}
}
long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx)
{
long ret;
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else {
#ifndef OPENSSL_EXTRA
ret = MAX_CHAIN_DEPTH;
#else
ret = ctx->verifyDepth;
#endif
}
return ret;
}
long wolfSSL_get_verify_depth(WOLFSSL* ssl)
{
long ret;
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
#ifndef OPENSSL_EXTRA
ret = MAX_CHAIN_DEPTH;
#else
ret = ssl->options.verifyDepth;
#endif
}
return ret;
}
#if defined(HAVE_RPK)
static int isArrayUnique(const char* buf, size_t len)
{
size_t i;
for (i = 0; i < len - 1; ++i) {
size_t j;
for (j = i + 1; j < len; ++j) {
if (buf[i] == buf[j]) {
return 0;
}
}
}
return 1;
}
static int set_cert_type(RpkConfig* cfg, int client, const char* buf,
int len)
{
int i;
byte* certTypeCnt;
byte* certTypes;
if ((cfg == NULL) || (len > (client ? MAX_CLIENT_CERT_TYPE_CNT :
MAX_SERVER_CERT_TYPE_CNT))) {
return BAD_FUNC_ARG;
}
if (client) {
certTypeCnt = &cfg->preferred_ClientCertTypeCnt;
certTypes = cfg->preferred_ClientCertTypes;
}
else {
certTypeCnt = &cfg->preferred_ServerCertTypeCnt;
certTypes = cfg->preferred_ServerCertTypes;
}
if ((buf == NULL) || (len == 0)) {
*certTypeCnt = 1;
for (i = 0; i < 2; i++) {
certTypes[i] = WOLFSSL_CERT_TYPE_X509;
}
return 1;
}
if (!isArrayUnique(buf, (size_t)len))
return BAD_FUNC_ARG;
for (i = 0; i < len; i++) {
if ((buf[i] != WOLFSSL_CERT_TYPE_RPK) &&
(buf[i] != WOLFSSL_CERT_TYPE_X509)) {
return BAD_FUNC_ARG;
}
certTypes[i] = (byte)buf[i];
}
*certTypeCnt = len;
return 1;
}
int wolfSSL_CTX_set_client_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len)
{
int ret;
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = set_cert_type(&ctx->rpkConfig, 1, buf, len);
}
return ret;
}
int wolfSSL_CTX_set_server_cert_type(WOLFSSL_CTX* ctx, const char* buf, int len)
{
int ret;
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = set_cert_type(&ctx->rpkConfig, 0, buf, len);
}
return ret;
}
int wolfSSL_set_client_cert_type(WOLFSSL* ssl, const char* buf, int len)
{
int ret;
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = set_cert_type(&ssl->options.rpkConfig, 1, buf, len);
}
return ret;
}
int wolfSSL_set_server_cert_type(WOLFSSL* ssl, const char* buf, int len)
{
int ret;
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = set_cert_type(&ssl->options.rpkConfig, 0, buf, len);
}
return ret;
}
int wolfSSL_get_negotiated_client_cert_type(WOLFSSL* ssl, int* tp)
{
int ret = 1;
if ((ssl == NULL) || (tp == NULL)) {
ret = BAD_FUNC_ARG;
}
else if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.rpkState.received_ClientCertTypeCnt == 1) {
*tp = ssl->options.rpkState.received_ClientCertTypes[0];
}
else {
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
}
else if (ssl->options.rpkState.sending_ClientCertTypeCnt == 1) {
*tp = ssl->options.rpkState.sending_ClientCertTypes[0];
}
else {
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
return ret;
}
int wolfSSL_get_negotiated_server_cert_type(WOLFSSL* ssl, int* tp)
{
int ret = 1;
if ((ssl == NULL) || (tp == NULL)) {
ret = BAD_FUNC_ARG;
}
else if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->options.rpkState.received_ServerCertTypeCnt == 1) {
*tp = ssl->options.rpkState.received_ServerCertTypes[0];
}
else {
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
}
else if (ssl->options.rpkState.sending_ServerCertTypeCnt == 1) {
*tp = ssl->options.rpkState.sending_ServerCertTypes[0];
}
else {
*tp = WOLFSSL_CERT_TYPE_UNKNOWN;
}
return ret;
}
#endif
typedef struct {
byte verifyPeer:1;
byte verifyNone:1;
byte failNoCert:1;
byte failNoCertxPSK:1;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
byte verifyPostHandshake:1;
#endif
} SetVerifyOptions;
static SetVerifyOptions ModeToVerifyOptions(int mode)
{
SetVerifyOptions opts;
XMEMSET(&opts, 0, sizeof(SetVerifyOptions));
if (mode != WOLFSSL_VERIFY_DEFAULT) {
opts.verifyNone = (mode == WOLFSSL_VERIFY_NONE);
if (!opts.verifyNone) {
opts.verifyPeer =
(mode & WOLFSSL_VERIFY_PEER) != 0;
opts.failNoCertxPSK =
(mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) != 0;
opts.failNoCert =
(mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) != 0;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
opts.verifyPostHandshake =
(mode & WOLFSSL_VERIFY_POST_HANDSHAKE) != 0;
#endif
}
}
return opts;
}
WOLFSSL_ABI void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode,
VerifyCallback verify_callback)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_verify");
if (ctx != NULL) {
SetVerifyOptions opts = ModeToVerifyOptions(mode);
ctx->verifyNone = opts.verifyNone;
ctx->verifyPeer = opts.verifyPeer;
ctx->failNoCert = opts.failNoCert;
ctx->failNoCertxPSK = opts.failNoCertxPSK;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ctx->verifyPostHandshake = opts.verifyPostHandshake;
#endif
ctx->verifyCallback = verify_callback;
}
}
#ifdef OPENSSL_ALL
void wolfSSL_CTX_set_cert_verify_callback(WOLFSSL_CTX* ctx,
CertVerifyCallback cb, void* arg)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_cert_verify_callback");
if (ctx != NULL) {
ctx->verifyCertCb = cb;
ctx->verifyCertCbArg = arg;
}
}
#endif
void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback verify_callback)
{
WOLFSSL_ENTER("wolfSSL_set_verify");
if (ssl != NULL) {
SetVerifyOptions opts = ModeToVerifyOptions(mode);
ssl->options.verifyNone = opts.verifyNone;
ssl->options.verifyPeer = opts.verifyPeer;
ssl->options.failNoCert = opts.failNoCert;
ssl->options.failNoCertxPSK = opts.failNoCertxPSK;
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
ssl->options.verifyPostHandshake = opts.verifyPostHandshake;
#endif
ssl->verifyCallback = verify_callback;
}
}
void wolfSSL_set_verify_result(WOLFSSL *ssl, long v)
{
WOLFSSL_ENTER("wolfSSL_set_verify_result");
if (ssl != NULL) {
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
ssl->peerVerifyRet = (unsigned long)v;
#else
WOLFSSL_STUB("wolfSSL_set_verify_result");
(void)v;
#endif
}
}
void wolfSSL_CTX_SetCertCbCtx(WOLFSSL_CTX* ctx, void* userCtx)
{
WOLFSSL_ENTER("wolfSSL_CTX_SetCertCbCtx");
if (ctx != NULL) {
ctx->verifyCbCtx = userCtx;
}
}
void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx)
{
WOLFSSL_ENTER("wolfSSL_SetCertCbCtx");
if (ssl != NULL) {
ssl->verifyCbCtx = ctx;
}
}
void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb)
{
if ((ctx != NULL) && (ctx->cm != NULL)) {
ctx->cm->caCacheCallback = cb;
}
}
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_TLS13) && \
defined(WOLFSSL_POST_HANDSHAKE_AUTH)
int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl)
{
int ret;
ret = wolfSSL_request_certificate(ssl);
if (ret != 1) {
if ((ssl != NULL) && !IsAtLeastTLSv1_3(ssl->version)) {
WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION);
}
else {
WOLFSSL_ERROR(ret);
}
ret = 0;
}
return ret;
}
int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val)
{
int ret;
if (wolfSSL_CTX_allow_post_handshake_auth(ctx) == 0) {
ctx->postHandshakeAuth = (val != 0);
ret = 1;
}
else {
ret = 0;
}
return ret;
}
int wolfSSL_set_post_handshake_auth(WOLFSSL* ssl, int val)
{
int ret;
if (wolfSSL_allow_post_handshake_auth(ssl) == 0) {
ssl->options.postHandshakeAuth = (val != 0);
ret = 1;
}
else {
ret = 0;
}
return ret;
}
#endif
#if defined(PERSIST_CERT_CACHE)
#if !defined(NO_FILESYSTEM)
int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache");
if ((ctx == NULL) || (fname == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
ret = CM_SaveCertCache(ctx->cm, fname);
}
return ret;
}
int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache");
if ((ctx == NULL) || (fname == NULL)) {
ret = BAD_FUNC_ARG;
}
else {
ret = CM_RestoreCertCache(ctx->cm, fname);
}
return ret;
}
#endif
int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem,
int sz, int* used)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache");
if ((ctx == NULL) || (mem == NULL) || (used == NULL) || (sz <= 0)) {
ret = BAD_FUNC_ARG;
}
else {
ret = CM_MemSaveCertCache(ctx->cm, mem, sz, used);
}
return ret;
}
int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache");
if ((ctx == NULL) || (mem == NULL) || (sz <= 0)) {
ret = BAD_FUNC_ARG;
}
else {
ret = CM_MemRestoreCertCache(ctx->cm, mem, sz);
}
return ret;
}
int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize");
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = CM_GetCertCacheMemSize(ctx->cm);
}
return ret;
}
#endif
int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl)
{
int ret = 1;
if (ssl == NULL) {
WOLFSSL_MSG("Null function arg");
ret = BAD_FUNC_ARG;
}
else {
if (ssl->buffers.weOwnCert && !ssl->keepCert) {
WOLFSSL_MSG("Unloading cert");
FreeDer(&ssl->buffers.certificate);
#ifdef KEEP_OUR_CERT
wolfSSL_X509_free(ssl->ourCert);
ssl->ourCert = NULL;
#endif
ssl->buffers.weOwnCert = 0;
}
if (ssl->buffers.weOwnCertChain) {
WOLFSSL_MSG("Unloading cert chain");
FreeDer(&ssl->buffers.certChain);
ssl->buffers.weOwnCertChain = 0;
}
if (ssl->buffers.weOwnKey) {
WOLFSSL_MSG("Unloading key");
if (ssl->buffers.key != NULL && ssl->buffers.key->buffer != NULL)
ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length);
FreeDer(&ssl->buffers.key);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.keyMask);
#endif
ssl->buffers.weOwnKey = 0;
}
#ifdef WOLFSSL_DUAL_ALG_CERTS
if (ssl->buffers.weOwnAltKey) {
WOLFSSL_MSG("Unloading alt key");
if (ssl->buffers.altKey != NULL &&
ssl->buffers.altKey->buffer != NULL) {
ForceZero(ssl->buffers.altKey->buffer,
ssl->buffers.altKey->length);
}
FreeDer(&ssl->buffers.altKey);
#ifdef WOLFSSL_BLIND_PRIVATE_KEY
FreeDer(&ssl->buffers.altKeyMask);
#endif
ssl->buffers.weOwnAltKey = 0;
}
#endif
}
return ret;
}
int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs");
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wolfSSL_CertManagerUnloadCAs(ctx->cm);
}
return ret;
}
int wolfSSL_CTX_UnloadIntermediateCerts(WOLFSSL_CTX* ctx)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_UnloadIntermediateCerts");
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else if ((ret = wolfSSL_RefWithMutexLock(&ctx->ref)) == 0) {
if (ctx->ref.count > 1) {
WOLFSSL_MSG("ctx object must have a ref count of 1 before "
"unloading intermediate certs");
ret = BAD_STATE_E;
}
else {
ret = wolfSSL_CertManagerUnloadIntermediateCerts(ctx->cm);
}
if (wolfSSL_RefWithMutexUnlock(&ctx->ref) != 0) {
WOLFSSL_MSG("Failed to unlock mutex!");
}
}
return ret;
}
#ifdef WOLFSSL_TRUST_PEER_CERT
int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
if (ctx == NULL) {
ret = BAD_FUNC_ARG;
}
else {
ret = wolfSSL_CertManagerUnload_trust_peers(ctx->cm);
}
return ret;
}
#ifdef WOLFSSL_LOCAL_X509_STORE
int wolfSSL_Unload_trust_peers(WOLFSSL* ssl)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers");
if (ssl == NULL) {
ret = BAD_FUNC_ARG;
}
else {
SSL_CM_WARNING(ssl);
return wolfSSL_CertManagerUnload_trust_peers(SSL_CM(ssl));
}
return ret;
}
#endif
#endif
#ifndef WOLFSSL_NO_CA_NAMES
static int add_to_ca_names_list(WOLFSSL_STACK* ca_names, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_X509_NAME *nameCopy = NULL;
nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(x509));
if (nameCopy == NULL) {
WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
ret = 0;
}
else if (wolfSSL_sk_X509_NAME_push(ca_names, nameCopy) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
wolfSSL_X509_NAME_free(nameCopy);
ret = 0;
}
return ret;
}
int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA");
if ((ctx == NULL) || (x509 == NULL)) {
WOLFSSL_MSG("Bad argument");
ret = 0;
}
else if (ctx->client_ca_names == NULL) {
ctx->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
if (ctx->client_ca_names == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
ret = 0;
}
}
if (ret == 1) {
ret = add_to_ca_names_list(ctx->client_ca_names, x509);
}
return ret;
}
int wolfSSL_add_client_CA(WOLFSSL* ssl, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_add_client_CA");
if ((ssl == NULL) || (x509 == NULL)) {
WOLFSSL_MSG("Bad argument");
ret = 0;
}
else if (ssl->client_ca_names == NULL) {
ssl->client_ca_names = wolfSSL_sk_X509_NAME_new(NULL);
if (ssl->client_ca_names == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
ret = 0;
}
}
if (ret == 1) {
ret = add_to_ca_names_list(ssl->client_ca_names, x509);
}
return ret;
}
int wolfSSL_CTX_add1_to_CA_list(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_CTX_add1_to_CA_list");
if ((ctx == NULL) || (x509 == NULL)) {
WOLFSSL_MSG("Bad argument");
ret = 0;
}
else if (ctx->ca_names == NULL) {
ctx->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
if (ctx->ca_names == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
ret = 0;
}
}
if (ret == 1) {
ret = add_to_ca_names_list(ctx->ca_names, x509);
}
return ret;
}
int wolfSSL_add1_to_CA_list(WOLFSSL* ssl, WOLFSSL_X509* x509)
{
int ret = 1;
WOLFSSL_ENTER("wolfSSL_add1_to_CA_list");
if ((ssl == NULL) || (x509 == NULL)) {
WOLFSSL_MSG("Bad argument");
ret = 0;
}
else if (ssl->ca_names == NULL) {
ssl->ca_names = wolfSSL_sk_X509_NAME_new(NULL);
if (ssl->ca_names == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
ret = 0;
}
}
if (ret == 1) {
ret = add_to_ca_names_list(ssl->ca_names, x509);
}
return ret;
}
void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx,
WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_client_CA_list");
if (ctx != NULL) {
wolfSSL_sk_X509_NAME_pop_free(ctx->client_ca_names, NULL);
ctx->client_ca_names = names;
}
}
void wolfSSL_set_client_CA_list(WOLFSSL* ssl,
WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
WOLFSSL_ENTER("wolfSSL_set_client_CA_list");
if (ssl != NULL) {
if (ssl->client_ca_names != ssl->ctx->client_ca_names) {
wolfSSL_sk_X509_NAME_pop_free(ssl->client_ca_names, NULL);
}
ssl->client_ca_names = names;
}
}
void wolfSSL_CTX_set0_CA_list(WOLFSSL_CTX* ctx,
WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
WOLFSSL_ENTER("wolfSSL_CTX_set0_CA_list");
if (ctx != NULL) {
wolfSSL_sk_X509_NAME_pop_free(ctx->ca_names, NULL);
ctx->ca_names = names;
}
}
void wolfSSL_set0_CA_list(WOLFSSL* ssl,
WOLF_STACK_OF(WOLFSSL_X509_NAME)* names)
{
WOLFSSL_ENTER("wolfSSL_set0_CA_list");
if (ssl != NULL) {
if (ssl->ca_names != ssl->ctx->ca_names) {
wolfSSL_sk_X509_NAME_pop_free(ssl->ca_names, NULL);
}
ssl->ca_names = names;
}
}
WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get_client_CA_list(
const WOLFSSL_CTX *ctx)
{
WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
WOLFSSL_ENTER("wolfSSL_CTX_get_client_CA_list");
if (ctx == NULL) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get_client_CA_list");
ret = NULL;
}
else {
ret = ctx->client_ca_names;
}
return ret;
}
WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get_client_CA_list(const WOLFSSL* ssl)
{
WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
WOLFSSL_ENTER("wolfSSL_get_client_CA_list");
if (ssl == NULL) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_get_client_CA_list");
ret = NULL;
}
else if (ssl->options.side == WOLFSSL_CLIENT_END) {
ret = ssl->peer_ca_names;
}
else {
ret = SSL_CLIENT_CA_NAMES(ssl);
}
return ret;
}
WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_CTX_get0_CA_list(
const WOLFSSL_CTX *ctx)
{
WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
WOLFSSL_ENTER("wolfSSL_CTX_get0_CA_list");
if (ctx == NULL) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_CTX_get0_CA_list");
ret = NULL;
}
else {
ret = ctx->ca_names;
}
return ret;
}
WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_CA_list(const WOLFSSL *ssl)
{
WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
WOLFSSL_ENTER("wolfSSL_get0_CA_list");
if (ssl == NULL) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_CA_list");
ret = NULL;
}
else {
ret = SSL_CA_NAMES(ssl);
}
return ret;
}
WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_get0_peer_CA_list(const WOLFSSL* ssl)
{
WOLF_STACK_OF(WOLFSSL_X509_NAME)* ret;
WOLFSSL_ENTER("wolfSSL_get0_peer_CA_list");
if (ssl == NULL) {
WOLFSSL_MSG("Bad argument passed to wolfSSL_get0_peer_CA_list");
ret = NULL;
}
else {
ret = ssl->peer_ca_names;
}
return ret;
}
#ifndef NO_BIO
WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname)
{
#ifdef OPENSSL_EXTRA
WOLFSSL_STACK *list = NULL;
WOLFSSL_BIO* bio = NULL;
WOLFSSL_X509 *cert = NULL;
int err = 0;
unsigned long error;
WOLFSSL_ENTER("wolfSSL_load_client_CA_file");
bio = wolfSSL_BIO_new_file(fname, "rb");
if (bio == NULL) {
WOLFSSL_MSG("wolfSSL_BIO_new_file error");
err = 1;
}
if (!err) {
list = wolfSSL_sk_X509_NAME_new(NULL);
if (list == NULL) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_new error");
err = 1;
}
}
while (!err && wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) {
WOLFSSL_X509_NAME *nameCopy;
nameCopy = wolfSSL_X509_NAME_dup(wolfSSL_X509_get_subject_name(cert));
if (nameCopy == NULL) {
WOLFSSL_MSG("wolfSSL_X509_NAME_dup error");
err = 1;
}
else {
nameCopy->x509 = NULL;
if (wolfSSL_sk_X509_NAME_push(list, nameCopy) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_X509_NAME_push error");
wolfSSL_X509_NAME_free(nameCopy);
err = 1;
}
}
wolfSSL_X509_free(cert);
cert = NULL;
}
CLEAR_ASN_NO_PEM_HEADER_ERROR(error);
if (err) {
wolfSSL_sk_X509_NAME_pop_free(list, NULL);
list = NULL;
}
wolfSSL_BIO_free(bio);
return list;
#else
(void)fname;
return NULL;
#endif
}
#endif
#endif
#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(const WOLFSSL_CTX* ctx)
{
WOLFSSL_X509_STORE* ret;
if (ctx == NULL) {
ret = NULL;
}
else if (ctx->x509_store_pt != NULL) {
ret = ctx->x509_store_pt;
}
else {
ret = (WOLFSSL_X509_STORE*)&ctx->x509_store;
}
return ret;
}
void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_cert_store");
if ((ctx == NULL) || (str == NULL) || (ctx->cm == str->cm)) {
WOLFSSL_MSG("Invalid parameters");
}
else if (wolfSSL_CertManager_up_ref(str->cm) != 1) {
WOLFSSL_MSG("wolfSSL_CertManager_up_ref error");
}
else {
wolfSSL_CertManagerFree(ctx->cm);
wolfSSL_X509_STORE_free(ctx->x509_store_pt);
ctx->cm = str->cm;
ctx->x509_store.cm = str->cm;
ctx->x509_store.cache = str->cache;
ctx->x509_store_pt = str;
ctx->cm->x509_store_p = ctx->x509_store_pt;
}
}
#ifdef OPENSSL_ALL
int wolfSSL_CTX_set1_verify_cert_store(WOLFSSL_CTX* ctx,
WOLFSSL_X509_STORE* str)
{
int ret;
WOLFSSL_ENTER("wolfSSL_CTX_set1_verify_cert_store");
if ((ctx == NULL) || (str == NULL)) {
WOLFSSL_MSG("Bad parameter");
ret = 0;
}
else if (str == CTX_STORE(ctx)) {
ret = 1;
}
else if (wolfSSL_X509_STORE_up_ref(str) != 1) {
WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
ret = 0;
}
else {
wolfSSL_X509_STORE_free(ctx->x509_store_pt);
ctx->x509_store_pt = str;
ret = 1;
}
return ret;
}
#endif
static int wolfssl_set_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str,
int ref)
{
int ret;
WOLFSSL_ENTER("wolfssl_set_verify_cert_store");
if ((ssl == NULL) || (str == NULL)) {
WOLFSSL_MSG("Bad parameter");
ret = 0;
}
else if (str == SSL_STORE(ssl)) {
ret = 1;
}
else if (ref && (wolfSSL_X509_STORE_up_ref(str) != 1)) {
WOLFSSL_MSG("wolfSSL_X509_STORE_up_ref error");
ret = 0;
}
else {
wolfSSL_X509_STORE_free(ssl->x509_store_pt);
if (str == ssl->ctx->x509_store_pt) {
ssl->x509_store_pt = NULL;
}
else {
ssl->x509_store_pt = str;
}
ret = 1;
}
return ret;
}
int wolfSSL_set0_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
{
WOLFSSL_ENTER("wolfSSL_set0_verify_cert_store");
return wolfssl_set_verify_cert_store(ssl, str, 0);
}
int wolfSSL_set1_verify_cert_store(WOLFSSL *ssl, WOLFSSL_X509_STORE* str)
{
WOLFSSL_ENTER("wolfSSL_set1_verify_cert_store");
return wolfssl_set_verify_cert_store(ssl, str, 1);
}
#endif
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
defined(KEEP_OUR_CERT)
WOLFSSL_X509* wolfSSL_CTX_get0_certificate(WOLFSSL_CTX* ctx)
{
WOLFSSL_X509* ret = NULL;
if (ctx == NULL) {
WOLFSSL_MSG("Invalid parameter");
}
else {
if (ctx->ourCert == NULL) {
if (ctx->certificate == NULL) {
WOLFSSL_MSG("Ctx Certificate buffer not set!");
}
#ifndef WOLFSSL_X509_STORE_CERTS
else {
ctx->ourCert = wolfSSL_X509_d2i_ex(NULL,
ctx->certificate->buffer, (int)ctx->certificate->length,
ctx->heap);
ctx->ownOurCert = 1;
}
#endif
}
ret = ctx->ourCert;
}
return ret;
}
WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl)
{
WOLFSSL_X509* ret = NULL;
if (ssl == NULL) {
WOLFSSL_MSG("Invalid parameter");
}
else if (ssl->buffers.weOwnCert) {
if (ssl->ourCert == NULL) {
if (ssl->ctx != NULL && ssl->ctx->ourCert != NULL) {
if (ssl->buffers.certificate == NULL ||
ssl->buffers.certificate->buffer == NULL ||
(ssl->buffers.certificate->length ==
ssl->ctx->certificate->length &&
XMEMCMP(ssl->buffers.certificate->buffer,
ssl->ctx->certificate->buffer,
ssl->buffers.certificate->length) == 0)) {
return ssl->ctx->ourCert;
}
}
if (ssl->buffers.certificate == NULL) {
WOLFSSL_MSG("Certificate buffer not set!");
}
#ifndef WOLFSSL_X509_STORE_CERTS
else {
ssl->ourCert = wolfSSL_X509_d2i_ex(NULL,
ssl->buffers.certificate->buffer,
(int)ssl->buffers.certificate->length, ssl->heap);
}
#endif
}
ret = ssl->ourCert;
}
else {
ret = wolfSSL_CTX_get0_certificate(ssl->ctx);
}
return ret;
}
#endif
#endif
#endif