First version for OpenSSL BIO compatibility

This commit is contained in:
Ludovic FLAMENT
2016-04-29 16:34:11 +02:00
parent b72c83e191
commit 1bd65cc8a9
26 changed files with 10442 additions and 411 deletions

View File

@@ -63,7 +63,22 @@ src_libwolfssl_la_SOURCES += \
wolfcrypt/src/hmac.c \
wolfcrypt/src/random.c \
wolfcrypt/src/sha256.c \
wolfcrypt/src/hash.c
wolfcrypt/src/hash.c \
wolfcrypt/src/bio.c \
wolfcrypt/src/bio_m_mem.c \
wolfcrypt/src/bio_m_file.c \
wolfcrypt/src/bio_m_fd.c \
wolfcrypt/src/bio_m_sock.c \
wolfcrypt/src/bio_m_conn.c \
wolfcrypt/src/bio_m_accept.c \
wolfcrypt/src/bio_m_dgram.c \
wolfcrypt/src/bio_m_null.c \
wolfcrypt/src/bio_f_sock.c \
wolfcrypt/src/bio_f_buff.c \
wolfcrypt/src/bio_f_cipher.c \
wolfcrypt/src/bio_f_b64.c \
wolfcrypt/src/bio_f_dgst.c \
wolfcrypt/src/bio_f_ssl.c
if !BUILD_USER_RSA
if BUILD_RSA

View File

@@ -625,7 +625,6 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
}
}
/* Set cipher pointers to null */
void InitCiphers(WOLFSSL* ssl)
{
@@ -671,6 +670,122 @@ void InitCiphers(WOLFSSL* ssl)
#endif
}
#ifdef OPENSSL_EXTRA
/* Set cipher pointers to null */
static void DupCiphers(WOLFSSL* ssl, WOLFSSL* ossl)
{
#ifdef BUILD_ARC4
if (ossl->encrypt.arc4 != NULL) {
ssl->encrypt.arc4 = (Arc4*)XMALLOC(sizeof(Arc4),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.arc4, ossl->encrypt.arc4, sizeof(Arc4));
}
if (ossl->decrypt.arc4 != NULL) {
ssl->decrypt.arc4 = (Arc4*)XMALLOC(sizeof(Arc4),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.arc4, ossl->decrypt.arc4, sizeof(Arc4));
}
#endif
#ifdef BUILD_DES3
if (ossl->encrypt.des3 != NULL) {
ssl->encrypt.des3 = (Des3*)XMALLOC(sizeof(Des3),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.des3, ossl->encrypt.des3, sizeof(Des3));
}
if (ossl->decrypt.des3 != NULL) {
ssl->decrypt.des3 = (Des3*)XMALLOC(sizeof(Des3),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.des3, ossl->decrypt.des3, sizeof(Des3));
}
#endif
#ifdef BUILD_AES
if (ossl->encrypt.aes != NULL) {
ssl->encrypt.aes = (Aes*)XMALLOC(sizeof(Aes),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.aes, ossl->encrypt.aes, sizeof(Aes));
}
if (ossl->decrypt.aes != NULL) {
ssl->decrypt.aes = (Aes*)XMALLOC(sizeof(Aes),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.aes, ossl->decrypt.aes, sizeof(Aes));
}
#endif
#ifdef HAVE_CAMELLIA
if (ossl->encrypt.cam != NULL) {
ssl->encrypt.cam = (Camellia*)XMALLOC(sizeof(Camellia),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.cam, ossl->encrypt.cam, sizeof(Camellia));
}
if (ossl->decrypt.cam != NULL) {
ssl->decrypt.cam = (Camellia*)XMALLOC(sizeof(Camellia),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.cam, ossl->decrypt.cam, sizeof(Camellia));
}
#endif
#ifdef HAVE_HC128
if (ossl->encrypt.hc128 != NULL) {
ssl->encrypt.hc128 = (HC128*)XMALLOC(sizeof(HC128),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.hc128, ossl->encrypt.hc128, sizeof(HC128));
}
if (ossl->decrypt.hc128 != NULL) {
ssl->decrypt.hc128 = (HC128*)XMALLOC(sizeof(HC128),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.hc128, ossl->decrypt.hc128, sizeof(HC128));
}
#endif
#ifdef BUILD_RABBIT
if (ossl->encrypt.rabbit != NULL) {
ssl->encrypt.rabbit = (Rabbit*)XMALLOC(sizeof(Rabbit),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.rabbit, ossl->encrypt.rabbit, sizeof(Rabbit));
}
if (ossl->decrypt.rabbit != NULL) {
ssl->decrypt.rabbit = (Rabbit*)XMALLOC(sizeof(Rabbit),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.rabbit, ossl->decrypt.rabbit, sizeof(Rabbit));
}
#endif
#ifdef HAVE_CHACHA
if (ossl->encrypt.chacha != NULL) {
ssl->encrypt.chacha = (ChaCha*)XMALLOC(sizeof(ChaCha),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.chacha, ossl->encrypt.chacha, sizeof(ChaCha));
}
if (ossl->decrypt.chacha != NULL) {
ssl->decrypt.chacha = (ChaCha*)XMALLOC(sizeof(ChaCha),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.chacha, ossl->decrypt.chacha, sizeof(ChaCha));
}
#endif
#ifdef HAVE_IDEA
if (ossl->encrypt.idea != NULL) {
ssl->encrypt.idea = (Idea*)XMALLOC(sizeof(Idea),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->encrypt.idea, ossl->encrypt.idea, sizeof(Idea));
}
if (ossl->decrypt.idea != NULL) {
ssl->decrypt.idea = (Idea*)XMALLOC(sizeof(Idea),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->decrypt.idea, ossl->decrypt.idea, sizeof(Idea));
}
#endif
#ifdef HAVE_POLY1305
if (ossl->auth.poly1305 != NULL) {
ssl->auth.poly1305 = (Poly1305*)XMALLOC(sizeof(Poly1305),
ssl->heap, DYNAMIC_TYPE_CIPHER);
XMEMCPY(ssl->auth.poly1305, ossl->auth.poly1305, sizeof(Poly1305));
}
#endif
ssl->encrypt.setup = ossl->encrypt.setup;
ssl->decrypt.setup = ossl->decrypt.setup;
#ifdef HAVE_ONE_TIME_AUTH
ssl->auth.setup = ossl->auth.setup;
#endif
}
#endif /* OPENSSL_EXTRA */
/* Free ciphers */
void FreeCiphers(WOLFSSL* ssl)
@@ -747,6 +862,23 @@ void InitCipherSpecs(CipherSpecs* cs)
cs->block_size = 0;
}
#ifdef OPENSSL_EXTRA
static void DupCipherSpecs(CipherSpecs* cs, CipherSpecs* ocs)
{
cs->bulk_cipher_algorithm = ocs->bulk_cipher_algorithm;
cs->cipher_type = ocs->cipher_type;
cs->mac_algorithm = ocs->mac_algorithm;
cs->kea = ocs->kea;
cs->sig_algo = ocs->sig_algo;
cs->hash_size = ocs->hash_size;
cs->static_ecdh = ocs->static_ecdh;
cs->key_size = ocs->key_size;
cs->iv_size = ocs->iv_size;
cs->block_size = ocs->block_size;
}
#endif /* OPENSSL_EXTRA */
static void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig,
int haveRSAsig, int haveAnon)
{
@@ -1621,6 +1753,20 @@ void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag)
}
}
#ifdef OPENSSL_EXTRA
static int DupX509Name(WOLFSSL_X509_NAME* name, WOLFSSL_X509_NAME* oname)
{
if (name == NULL || oname == NULL)
return BAD_FUNC_ARG;
name->name = name->staticName;
XMEMCPY(name->staticName, oname->staticName, sizeof(oname->staticName));
name->dynamicName = oname->dynamicName;
XMEMCPY(&name->fullName, &oname->fullName, sizeof(DecodedName));
return 0;
}
#endif /* OPENSSL_EXTRA */
void FreeX509Name(WOLFSSL_X509_NAME* name)
{
@@ -1676,6 +1822,79 @@ void InitX509(WOLFSSL_X509* x509, int dynamicFlag)
#endif /* OPENSSL_EXTRA */
}
#ifdef OPENSSL_EXTRA
static int DupX509(WOLFSSL_X509* x509, WOLFSSL_X509* ox509)
{
if (x509 == NULL || ox509 == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return BAD_FUNC_ARG;
}
DupX509Name(&x509->issuer, &ox509->issuer);
DupX509Name(&x509->subject, &ox509->subject);
x509->version = ox509->version;
if (ox509->pubKey.buffer != NULL)
XMEMCPY(x509->pubKey.buffer, ox509->pubKey.buffer, sizeof(Buffers));
if (ox509->sig.buffer != NULL)
XMEMCPY(x509->sig.buffer, ox509->sig.buffer, sizeof(Buffers));
if (ox509->derCert.buffer != NULL)
XMEMCPY(x509->derCert.buffer, ox509->derCert.buffer, sizeof(Buffers));
if (ox509->altNames != NULL)
XMEMCPY(x509->altNames, ox509->altNames, sizeof(DNS_entry));
if (ox509->altNamesNext != NULL)
XMEMCPY(x509->altNamesNext, ox509->altNamesNext, sizeof(DNS_entry));
x509->dynamicMemory = ox509->dynamicMemory;
x509->isCa = ox509->isCa;
#ifdef HAVE_ECC
x509->pkCurveOID = ox509->pkCurveOID;
#endif /* HAVE_ECC */
x509->pathLength = ox509->pathLength;
x509->basicConstSet = ox509->basicConstSet;
x509->basicConstCrit = ox509->basicConstCrit;
x509->basicConstPlSet = ox509->basicConstPlSet;
x509->subjAltNameSet = ox509->subjAltNameSet;
x509->subjAltNameCrit = ox509->subjAltNameCrit;
x509->authKeyIdSet = ox509->authKeyIdSet;
x509->authKeyIdCrit = ox509->authKeyIdCrit;
if (ox509->authKeyId != NULL && ox509->authKeyIdSz) {
x509->authKeyId = (byte*)XMALLOC(ox509->authKeyIdSz, NULL,
DYNAMIC_TYPE_X509_EXT);
if (x509->authKeyId == NULL)
return MEMORY_E;
XMEMCPY(x509->authKeyId, ox509->authKeyId, ox509->authKeyIdSz);
x509->authKeyIdSz = ox509->authKeyIdSz;
}
x509->subjKeyIdSet = ox509->subjKeyIdSet;
x509->subjKeyIdCrit = ox509->subjKeyIdCrit;
if (ox509->subjKeyId != NULL && ox509->subjKeyIdSz) {
x509->subjKeyId = (byte*)XMALLOC(ox509->subjKeyIdSz, NULL,
DYNAMIC_TYPE_X509_EXT);
if (x509->subjKeyId == NULL)
return MEMORY_E;
XMEMCPY(x509->subjKeyId, ox509->subjKeyId, ox509->subjKeyIdSz);
x509->subjKeyIdSz = ox509->subjKeyIdSz;
}
x509->keyUsageSet = ox509->keyUsageSet;
x509->keyUsageCrit = ox509->keyUsageCrit;
x509->keyUsage = ox509->keyUsage;
#ifdef WOLFSSL_SEP
x509->certPolicySet = ox509->certPolicySet;
x509->certPolicyCrit = ox509->certPolicyCrit;
#endif /* WOLFSSL_SEP */
return 0;
}
#endif /* OPENSSL_EXTRA */
/* Free wolfSSL X509 type */
void FreeX509(WOLFSSL_X509* x509)
@@ -1800,6 +2019,7 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
return BAD_MUTEX_E;
}
ctx->refCount++;
UnLockMutex(&ctx->countMutex);
ssl->ctx = ctx; /* only for passing to calls, options could change */
ssl->version = ctx->method->version;
@@ -2077,6 +2297,314 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
}
#ifdef OPENSSL_EXTRA
static int DupArrays(Arrays *arrays, Arrays *oarrays, void *heap)
{
if (arrays == NULL || oarrays == NULL) {
WOLFSSL_MSG("need valid arrays objects");
return BAD_FUNC_ARG;
}
if (oarrays->pendingMsg != NULL && oarrays->pendingMsgSz) {
arrays->pendingMsg = (byte *)XMALLOC(oarrays->pendingMsgSz, heap, DYNAMIC_TYPE_SSL);
if (arrays->pendingMsg == NULL)
return MEMORY_E;
XMEMCPY(arrays->pendingMsg, oarrays->pendingMsg, oarrays->pendingMsgSz);
arrays->pendingMsgSz = oarrays->pendingMsgSz;
}
arrays->pendingMsgOffset = oarrays->pendingMsgOffset;
arrays->preMasterSz = oarrays->preMasterSz;
#ifndef NO_PSK
arrays->psk_keySz = oarrays->psk_keySz;
XMEMCPY(arrays->client_identity, oarrays->client_identity,
sizeof(oarrays->client_identity));
XMEMCPY(arrays->server_hint, oarrays->server_hint,
sizeof(oarrays->server_hint));
XMEMCPY(arrays->psk_key, oarrays->psk_key,
sizeof(oarrays->psk_key));
#endif
XMEMCPY(arrays->clientRandom, oarrays->clientRandom,
sizeof(oarrays->clientRandom));
XMEMCPY(arrays->serverRandom, oarrays->serverRandom,
sizeof(oarrays->serverRandom));
XMEMCPY(arrays->sessionID, oarrays->sessionID,
sizeof(oarrays->sessionID));
XMEMCPY(arrays->preMasterSecret, oarrays->preMasterSecret,
sizeof(oarrays->preMasterSecret));
XMEMCPY(arrays->masterSecret, oarrays->masterSecret,
sizeof(oarrays->masterSecret));
arrays->sessionIDSz = oarrays->sessionIDSz;
#ifdef WOLFSSL_DTLS
XMEMCPY(arrays->cookie, oarrays->cookie, sizeof(oarrays->cookie));
arrays->cookieSz = oarrays->cookieSz;
#endif
arrays->pendingMsgType = oarrays->pendingMsgType;
return 0;
}
static int DupBufferStatic(bufferStatic *buf, bufferStatic *obuf,
void *heap, int type)
{
if (buf == NULL || obuf == NULL) {
WOLFSSL_MSG("need valid BufferStatic objects");
return BAD_FUNC_ARG;
}
buf->dynamicFlag = obuf->dynamicFlag;
buf->bufferSize = obuf->bufferSize;
buf->length = obuf->length;
buf->idx = obuf->idx;
buf->offset = obuf->offset;
XMEMCPY(buf->staticBuffer, obuf->staticBuffer, sizeof(obuf->staticBuffer));
if (buf->dynamicFlag) {
buf->buffer = XMALLOC(buf->bufferSize, heap, type);
if (buf->buffer == NULL)
return MEMORY_E;
XMEMCPY(buf->buffer, obuf->buffer, obuf->bufferSize);
}
else
buf->buffer = buf->staticBuffer;
return 0;
}
static int DupBuffer(buffer *buf, buffer *obuf, void *heap)
{
if (buf == NULL || obuf == NULL) {
WOLFSSL_MSG("need valid Buffer objects");
return BAD_FUNC_ARG;
}
buf->length = obuf->length;
if (obuf->buffer != NULL && obuf->length) {
buf->buffer = XMALLOC(buf->length, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (buf->buffer == NULL)
return MEMORY_E;
XMEMCPY(buf->buffer, obuf->buffer, obuf->length);
}
return 0;
}
static int DupBuffers(Buffers *buf, Buffers *obuf, void *heap)
{
int ret;
if (buf == NULL || obuf == NULL) {
WOLFSSL_MSG("need valid Buffers objects");
return BAD_FUNC_ARG;
}
ret = DupBufferStatic(&buf->inputBuffer, &obuf->inputBuffer,
heap, DYNAMIC_TYPE_IN_BUFFER);
if (ret != 0)
return ret;
ret = DupBufferStatic(&buf->outputBuffer, &obuf->outputBuffer,
heap, DYNAMIC_TYPE_OUT_BUFFER);
if (ret != 0)
return ret;
ret = DupBuffer(&buf->domainName, &obuf->domainName, heap);
if (ret != 0)
return ret;
buf->clearOutputBuffer = obuf->clearOutputBuffer;
buf->prevSent = obuf->prevSent;
buf->plainSz = obuf->plainSz;
buf->weOwnCert = obuf->weOwnCert;
buf->weOwnCertChain = obuf->weOwnCertChain;
buf->weOwnDH = obuf->weOwnDH;
buf->weOwnKey = obuf->weOwnKey;
#ifndef NO_DH
ret = DupBuffer(&buf->serverDH_Pub, &obuf->serverDH_Pub, heap);
if (ret != 0)
return ret;
ret = DupBuffer(&buf->serverDH_Priv, &obuf->serverDH_Priv, heap);
if (ret != 0)
return ret;
#endif
#ifndef NO_CERTS
/* ctx still owns certificate, certChain, key, dh, and cm */
buf->certificate = obuf->certificate;
buf->certChain = obuf->certChain;
buf->key = obuf->key;
#endif
#ifdef WOLFSSL_DTLS
XMEMCPY(&buf->dtlsCtx, &obuf->dtlsCtx, sizeof(WOLFSSL_DTLS_CTX));
#ifndef NO_WOLFSSL_SERVER
ret = DupBuffer(&buf->dtlsCookieSecret, &obuf->dtlsCookieSecret, heap);
if (ret != 0)
return ret;
#endif /* NO_WOLFSSL_SERVER */
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ret = DupBuffer(&buf->peerEccDsaKey, &obuf->peerEccDsaKey, heap);
if (ret != 0)
return ret;
#endif /* HAVE_ECC */
#ifndef NO_RSA
ret = DupBuffer(&buf->peerRsaKey, &obuf->peerRsaKey, heap);
if (ret != 0)
return ret;
#endif /* NO_RSA */
#endif /* HAVE_PK_CALLBACKS */
return 0;
}
/* init everything to 0, NULL, default values before calling anything that may
fail so that destructor has a "good" state to cleanup
0 on success */
int DupSSL(WOLFSSL* ssl, WOLFSSL* ossl)
{
int ret;
if (ssl == NULL || ossl == NULL) {
WOLFSSL_MSG("need valid ssl objects");
return BAD_FUNC_ARG;
}
ret = DupBuffers(&ssl->buffers, &ossl->buffers, ssl->heap);
if (ret != 0)
return ret;
/* Don't copy if (p,g) owned by ctx */
if (ssl->buffers.weOwnDH || ssl->options.side == WOLFSSL_CLIENT_END) {
ret = DupBuffer(&ssl->buffers.serverDH_P,
&ossl->buffers.serverDH_P, ssl->heap);
if (ret != 0)
return ret;
ret = DupBuffer(&ssl->buffers.serverDH_G,
&ossl->buffers.serverDH_G, ssl->heap);
if (ret != 0)
return ret;
}
#ifdef KEEP_PEER_CERT
ret = DupX509(&ssl->peerCert, &ossl->peerCert);
if (ret != 0)
return ret;
#endif
ssl->rfd = ossl->rfd;
ssl->wfd = ossl->wfd;
ssl->IOCB_ReadCtx = &ssl->rfd;
ssl->IOCB_WriteCtx = &ssl->wfd;
#ifdef HAVE_NETX
ssl->IOCB_ReadCtx = &ssl->nxCtx;
ssl->IOCB_WriteCtx = &ssl->nxCtx;
#endif
#ifdef WOLFSSL_DTLS
ssl->dtls_expected_rx = ossl->dtls_expected_rx;
#endif
/* options */
XMEMCPY(&ssl->options, &ossl->options, sizeof(Options));
#ifdef WOLFSSL_DTLS
ssl->dtls_timeout_init = ossl->dtls_timeout_init;
ssl->dtls_timeout_max = ossl->dtls_timeout_max;
ssl->dtls_timeout = ossl->dtls_timeout;
#endif
ssl->hmac = ossl->hmac;
#ifdef WOLFSSL_DTLS
ssl->buffers.dtlsCtx.fd = ossl->buffers.dtlsCtx.fd;
#endif
ssl->cipher.ssl = ssl;
#ifdef HAVE_TLS_EXTENSIONS
#ifdef HAVE_MAX_FRAGMENT
ssl->max_fragment = ossl->max_fragment;
#endif
#ifdef HAVE_ALPN
ssl->alpn_client_list = ossl->alpn_client_list;
#endif
#endif
/* default alert state (none) */
ssl->alert_history.last_rx.code = ossl->alert_history.last_rx.code;
ssl->alert_history.last_rx.level = ossl->alert_history.last_rx.level;
ssl->alert_history.last_tx.code = ossl->alert_history.last_tx.code;
ssl->alert_history.last_tx.level = ossl->alert_history.last_tx.level;
DupCiphers(ssl, ossl);
DupCipherSpecs(&ssl->specs, &ossl->specs);
/* arrays */
ret = DupArrays(ssl->arrays, ossl->arrays, ssl->heap);
if (ret != 0)
return ret;
/* suites */
XMEMCPY(ssl->suites, ossl->suites, sizeof(Suites));
/* versions */
XMEMCPY(&ssl->version, &ossl->version, sizeof(ProtocolVersion));
XMEMCPY(&ssl->chVersion, &ossl->chVersion, sizeof(ProtocolVersion));
/* hsHashes */
XMEMCPY(&ssl->hsHashes->verifyHashes, &ossl->hsHashes->verifyHashes,
sizeof(Hashes));
XMEMCPY(&ssl->hsHashes->certHashes, &ossl->hsHashes->certHashes,
sizeof(Hashes));
#ifndef NO_OLD_TLS
#ifndef NO_MD5
XMEMCPY(&ssl->hsHashes->hashMd5, &ossl->hsHashes->hashMd5, sizeof(Md5));
#endif
#ifndef NO_SHA
XMEMCPY(&ssl->hsHashes->hashSha, &ossl->hsHashes->hashSha, sizeof(Sha));
#endif
#endif
#ifndef NO_SHA256
XMEMCPY(&ssl->hsHashes->hashSha256, &ossl->hsHashes->hashSha256, sizeof(Sha256));
#endif
#ifdef WOLFSSL_SHA384
XMEMCPY(&ssl->hsHashes->hashSha384, &ossl->hsHashes->hashSha384, sizeof(Sha384));
#endif
#ifdef WOLFSSL_SHA512
XMEMCPY(&ssl->hsHashes->hashSha512, &ossl->hsHashes->hashSha512, sizeof(Sha512));
#endif
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) {
ssl->buffers.dtlsCookieSecret.length = ossl->buffers.dtlsCookieSecret.length;
XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer,
ossl->buffers.dtlsCookieSecret.buffer,
ossl->buffers.dtlsCookieSecret.length);
}
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
#ifdef HAVE_SECRET_CALLBACK
ssl->sessionSecretCb = ossl->sessionSecretCb;
ssl->sessionSecretCtx = ossl->sessionSecretCtx;
#endif
return 0;
}
#endif /* OPENSSL_EXTRA */
/* free use of temporary arrays */
void FreeArrays(WOLFSSL* ssl, int keep)
{
@@ -2104,6 +2632,7 @@ void SSL_ResourceFree(WOLFSSL* ssl)
* example with the RNG, it isn't used beyond the handshake except when
* using stream ciphers where it is retained. */
WOLFSSL_ENTER("SSL_ResourceFree");
FreeCiphers(ssl);
FreeArrays(ssl, 0);
wc_FreeRng(ssl->rng);
@@ -2166,8 +2695,8 @@ void SSL_ResourceFree(WOLFSSL* ssl)
#endif /* WOLFSSL_DTLS */
#if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS)
if (ssl->biord != ssl->biowr) /* only free write if different */
wolfSSL_BIO_free(ssl->biowr);
wolfSSL_BIO_free(ssl->biord); /* always free read bio */
WOLFCRYPT_BIO_free(ssl->biowr);
WOLFCRYPT_BIO_free(ssl->biord); /* always free read bio */
#endif
#ifdef HAVE_LIBZ
FreeStreams(ssl);
@@ -10518,7 +11047,7 @@ int GetCipherNamesSize(void)
/**
Set the enabled cipher suites.
Set the enabled cipher suites->
@param [out] suites Suites structure.
@param [in] list List of cipher suites, only supports full name from
@@ -13990,7 +14519,6 @@ int DoSessionTicket(WOLFSSL* ssl,
}
#endif
switch(ssl->specs.kea)
{
#ifndef NO_PSK
@@ -14481,6 +15009,7 @@ int DoSessionTicket(WOLFSSL* ssl,
}
wc_ecc_init(ssl->eccTempKey);
}
if (ssl->eccTempKeyPresent == 0) {
if (wc_ecc_make_key(ssl->rng, ssl->eccTempKeySz,
ssl->eccTempKey) != 0) {
@@ -14500,6 +15029,7 @@ int DoSessionTicket(WOLFSSL* ssl,
if (wc_ecc_export_x963(ssl->eccTempKey, exportBuf, &expSz) != 0) {
ERROR_OUT(ECC_EXPORT_ERROR, done_a);
}
length += expSz;
preSigSz = length;
@@ -15809,7 +16339,7 @@ int DoSessionTicket(WOLFSSL* ssl,
return SUITES_ERROR;
/* start with best, if a match we are good */
for (i = 0; i < ssl->suites->suiteSz; i += 2)
for (j = 0; j < peerSuites->suiteSz; j += 2)
for (j = 0; j < peerSuites->suiteSz; j += 2) {
if (ssl->suites->suites[i] == peerSuites->suites[j] &&
ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) {
@@ -15828,7 +16358,9 @@ int DoSessionTicket(WOLFSSL* ssl,
WOLFSSL_MSG("Could not verify suite validity, continue");
}
}
}
WOLFSSL_MSG("Could not find matching suite");
return MATCH_SUITE_ERROR;
}

846
src/ssl.c

File diff suppressed because it is too large Load Diff

823
wolfcrypt/src/bio.c Normal file
View File

@@ -0,0 +1,823 @@
/* bio.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <stdarg.h>
#include <stdio.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_METHOD *method)
{
WOLFCRYPT_BIO *bio;
WOLFSSL_ENTER("WOLFCRYPT_BIO_new");
if (method == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
bio = (WOLFCRYPT_BIO *)XMALLOC(sizeof(WOLFCRYPT_BIO),
0, DYNAMIC_TYPE_OPENSSL);
if (bio == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return NULL;
}
if (!WOLFCRYPT_BIO_set(bio, method)) {
XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
if (InitMutex(&bio->refMutex) < 0) {
WOLFSSL_MSG("Mutex error on BIO init");
return NULL;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_new", 1);
return bio;
}
int WOLFCRYPT_BIO_set(WOLFCRYPT_BIO *bio, WOLFCRYPT_BIO_METHOD *method)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_set");
if (bio == NULL || method == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_set", 0);
return 0;
}
bio->method = method;
bio->callback = NULL;
bio->cb_arg = NULL;
bio->init = 0;
bio->shutdown = 1;
bio->flags = 0;
bio->retry_reason = 0;
bio->num = 0;
bio->ptr = NULL;
bio->prev_bio = NULL;
bio->next_bio = NULL;
bio->references = 1;
bio->num_read = 0;
bio->num_write = 0;
if (method->create != NULL)
if (!method->create(bio)) {
WOLFSSL_ERROR(BIO_CREATE_METHOD_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_set", 0);
return 0;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_set", 1);
return 1;
}
int WOLFCRYPT_BIO_free(WOLFCRYPT_BIO *bio)
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_free", 0);
return 0;
}
if (LockMutex(&bio->refMutex) != 0) {
WOLFSSL_MSG("Couldn't lock bio mutex");
return 0;
}
bio->references--;
if (bio->references > 0) {
UnLockMutex(&bio->refMutex);
return 1;
}
else if (bio->references < 0) {
WOLFSSL_ERROR(BIO_BAD_REF);
WOLFSSL_MSG("WOLFCRYPT_BIO_free bad bio references");
UnLockMutex(&bio->refMutex);
return 0;
}
UnLockMutex(&bio->refMutex);
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_FREE, NULL, 0, 0, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_free", (int)ret);
return (int)(ret);
}
}
if (bio->method != NULL && bio->method->destroy != NULL)
bio->method->destroy(bio);
/* free refMutex */
FreeMutex(&bio->refMutex);
/* free bio */
XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL);
bio = NULL;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_free", 1);
return 1;
}
void WOLFCRYPT_BIO_clear_flags(WOLFCRYPT_BIO *bio, int flags)
{
bio->flags &= ~flags;
}
void WOLFCRYPT_BIO_set_flags(WOLFCRYPT_BIO *bio, int flags)
{
bio->flags |= flags;
}
int WOLFCRYPT_BIO_test_flags(const WOLFCRYPT_BIO *bio, int flags)
{
return (bio->flags & flags);
}
long (*WOLFCRYPT_BIO_get_callback(const WOLFCRYPT_BIO *bio))
(WOLFCRYPT_BIO *, int, const char *, int, long, long)
{
return bio->callback;
}
void WOLFCRYPT_BIO_set_callback(WOLFCRYPT_BIO *bio,
long (*cb) (WOLFCRYPT_BIO *, int, const char *,
int, long, long))
{
bio->callback = cb;
}
void WOLFCRYPT_BIO_set_callback_arg(WOLFCRYPT_BIO *bio, char *arg)
{
bio->cb_arg = arg;
}
char *WOLFCRYPT_BIO_get_callback_arg(const WOLFCRYPT_BIO *bio)
{
return bio->cb_arg;
}
const char *WOLFCRYPT_BIO_method_name(const WOLFCRYPT_BIO *bio)
{
return bio->method->name;
}
int WOLFCRYPT_BIO_method_type(const WOLFCRYPT_BIO *bio)
{
return bio->method->type;
}
int WOLFCRYPT_BIO_read(WOLFCRYPT_BIO *bio, void *data, int size)
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_read");
if ((bio == NULL) || (bio->method == NULL) ||
(bio->method->bread == NULL) || (data == NULL)) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_read", -2);
return -2;
}
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_READ, data, size, 0, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_read", (int)ret);
return (int)(ret);
}
}
if (!bio->init) {
WOLFSSL_ERROR(BIO_UNINITIALIZED_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_read", -2);
return -2;
}
ret = bio->method->bread(bio, data, size);
if (ret > 0)
bio->num_read += (unsigned long)ret;
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_READ | BIO_CB_RETURN,
data, size, 0, ret);
if (ret <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_read", (int)ret);
return (int)ret;
}
int WOLFCRYPT_BIO_write(WOLFCRYPT_BIO *bio, const void *data, int size)
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_write");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_write", 0);
return 0;
}
if ((bio->method == NULL) || (bio->method->bwrite == NULL) || (data == NULL))
{
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_write", -2);
return -2;
}
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_WRITE, data, size, 0, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_write", (int)ret);
return (int)(ret);
}
}
if (!bio->init) {
WOLFSSL_ERROR(BIO_UNINITIALIZED_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_write", -2);
return -2;
}
ret = bio->method->bwrite(bio, data, size);
if (ret > 0)
bio->num_write += (unsigned long)ret;
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_WRITE | BIO_CB_RETURN,
data, size, 0, ret);
if (ret <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_write", (int)ret);
return (int)ret;
}
int WOLFCRYPT_BIO_puts(WOLFCRYPT_BIO *bio, const char *data)
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_puts");
if ((bio == NULL) || (bio->method == NULL) ||
(bio->method->bputs == NULL) || (data == NULL)) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_puts", -2);
return -2;
}
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_PUTS, data, 0, 0, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_puts", (int)ret);
return (int)(ret);
}
}
if (!bio->init) {
WOLFSSL_ERROR(BIO_UNINITIALIZED_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_puts", -2);
return -2;
}
ret = bio->method->bputs(bio, data);
if (ret > 0)
bio->num_write += (unsigned long)ret;
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_PUTS | BIO_CB_RETURN,
data, 0, 0, ret);
if (ret <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_puts", (int)ret);
return (int)ret;
}
int WOLFCRYPT_BIO_gets(WOLFCRYPT_BIO *bio, char *data, int size)
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_gets");
if ((bio == NULL) || (bio->method == NULL) ||
(bio->method->bgets == NULL) || (data == NULL)) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_gets", -2);
return -2;
}
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_GETS, data, size, 0, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_gets", (int)ret);
return (int)(ret);
}
}
if (!bio->init) {
WOLFSSL_ERROR(BIO_UNINITIALIZED_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_gets", -2);
return -2;
}
ret = bio->method->bgets(bio, data, size);
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_GETS | BIO_CB_RETURN,
data, size, 0, ret);
if (ret <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_gets", (int)ret);
return (int)ret;
}
long WOLFCRYPT_BIO_ctrl(WOLFCRYPT_BIO *bio, int cmd, long larg, void *parg)
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_ctrl");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_ctrl bio", 0);
return 0;
}
if ((bio->method == NULL) || (bio->method->ctrl == NULL)) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_ctrl method method-ctrl", -2);
return -2;
}
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_CTRL, parg, cmd, larg, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_ctrl callback", (int)ret);
return ret;
}
}
ret = bio->method->ctrl(bio, cmd, larg, parg);
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN,
parg, cmd, larg, ret);
if (ret <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_ctrl", (int)ret);
return ret;
}
long WOLFCRYPT_BIO_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
void (*fp) (WOLFCRYPT_BIO *, int, const char *,
int, long, long))
{
long ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_callback_ctrl");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_callback_ctrl", 0);
return 0;
}
if ((bio->method == NULL) || (bio->method->callback_ctrl == NULL)) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_callback_ctrl", -2);
return -2;
}
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_callback_ctrl", (int)ret);
return ret;
}
}
ret = bio->method->callback_ctrl(bio, cmd, fp);
/* callback if set */
if (bio->callback != NULL) {
ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN,
(void *)&fp, cmd, 0, ret);
if (ret <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_callback_ctrl", (int)ret);
return ret;
}
int WOLFCRYPT_BIO_indent(WOLFCRYPT_BIO *bio, int indent, int max)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_indent");
if (indent < 0)
indent = 0;
if (indent > max)
indent = max;
while (indent--)
if (WOLFCRYPT_BIO_puts(bio, " ") != 1) {
WOLFSSL_ERROR(BIO_PUTS_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_indent", 0);
return 0;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_indent", 1);
return 1;
}
long WOLFCRYPT_BIO_int_ctrl(WOLFCRYPT_BIO *bio, int cmd, long larg, int iarg)
{
int i = iarg;
return WOLFCRYPT_BIO_ctrl(bio, cmd, larg, (char *)&i);
}
char *WOLFCRYPT_BIO_ptr_ctrl(WOLFCRYPT_BIO *bio, int cmd, long larg)
{
char *p = NULL;
WOLFSSL_ENTER("WOLFCRYPT_BIO_ptr_ctrl");
if (WOLFCRYPT_BIO_ctrl(bio, cmd, larg, (char *)&p) <= 0) {
WOLFSSL_ERROR(BIO_CTRL_E);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_ptr_ctrl", 0);
return NULL;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_ptr_ctrl", 1);
return p;
}
size_t WOLFCRYPT_BIO_ctrl_pending(WOLFCRYPT_BIO *bio)
{
return WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
}
size_t WOLFCRYPT_BIO_ctrl_wpending(WOLFCRYPT_BIO *bio)
{
return WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
}
/* put the 'bio' on the end of b's list of operators */
WOLFCRYPT_BIO *WOLFCRYPT_BIO_push(WOLFCRYPT_BIO *top, WOLFCRYPT_BIO *next)
{
WOLFCRYPT_BIO *tmp;
WOLFSSL_ENTER("WOLFCRYPT_BIO_push");
if (top == NULL) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_push", 0);
return next;
}
tmp = top;
while (tmp->next_bio != NULL)
tmp = tmp->next_bio;
tmp->next_bio = next;
if (next != NULL)
next->prev_bio = tmp;
/* called to do internal processing */
WOLFCRYPT_BIO_ctrl(top, BIO_CTRL_PUSH, 0, tmp);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_push", 1);
return top;
}
/* Remove the first and return the rest */
WOLFCRYPT_BIO *WOLFCRYPT_BIO_pop(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO *ret;
WOLFSSL_ENTER("WOLFCRYPT_BIO_pop");
if (bio == NULL)
return NULL;
ret = bio->next_bio;
WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_POP, 0, bio);
if (bio->prev_bio != NULL)
bio->prev_bio->next_bio = bio->next_bio;
if (bio->next_bio != NULL)
bio->next_bio->prev_bio = bio->prev_bio;
bio->next_bio = NULL;
bio->prev_bio = NULL;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_pop", 1);
return ret;
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_get_retry_BIO(WOLFCRYPT_BIO *bio, int *reason)
{
WOLFCRYPT_BIO *b, *last;
WOLFSSL_ENTER("WOLFCRYPT_BIO_get_retry_BIO");
b = last = bio;
for (; b != NULL; ) {
if (!WOLFCRYPT_BIO_should_retry(b))
break;
last = b;
b = b->next_bio;
}
if (reason != NULL)
*reason = last->retry_reason;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_get_retry_BIO", 1);
return last;
}
int WOLFCRYPT_BIO_get_retry_reason(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_get_retry_reason");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_get_retry_reason", -1);
return -1;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_get_retry_reason", (int)bio->retry_reason);
return bio->retry_reason;
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_find_type(WOLFCRYPT_BIO *bio, int type)
{
int mt, mask;
WOLFSSL_ENTER("WOLFCRYPT_BIO_find_type");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_find_type", -1);
return NULL;
}
mask = type & 0xff;
do {
if (bio->method != NULL) {
mt = bio->method->type;
if (!mask) {
if (mt & type) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_find_type", type);
return bio;
}
}
else if (mt == type) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_find_type", type);
return bio;
}
}
bio = bio->next_bio;
} while (bio != NULL);
WOLFSSL_ERROR(BIO_FIND_TYPE_E);
return NULL;
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_next(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_next");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_next", 0);
return NULL;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_next", 1);
return bio->next_bio;
}
void WOLFCRYPT_BIO_free_all(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO *b;
int ref;
WOLFSSL_ENTER("WOLFCRYPT_BIO_free_all");
while (bio != NULL) {
b = bio;
ref = b->references;
bio = bio->next_bio;
WOLFCRYPT_BIO_free(b);
if (ref > 1)
break;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_free_all", 1);
}
unsigned long WOLFCRYPT_BIO_number_read(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("BIO_number_read");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_number_read", 0);
return 0;
}
WOLFSSL_LEAVE("BIO_number_read", (int)bio->num_read);
return bio->num_read;
}
unsigned long WOLFCRYPT_BIO_number_written(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("BIO_number_written");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_number_written", 0);
return 0;
}
WOLFSSL_LEAVE("BIO_number_written", (int)bio->num_write);
return bio->num_write;
}
__attribute__((format(printf, 2, 3)))
int WOLFCRYPT_BIO_printf(WOLFCRYPT_BIO *bio, const char *format, ...)
{
int size, ret;
va_list args, args2;
char *buffer = NULL;
va_start(args, format);
/* save a copy of va_list to be able to parse 2 times */
va_copy(args2, args);
/* compute the required size for buffer */
#if defined(USE_WINDOWS_API)
size = _vscprintf(format, args);
#else
size = vsnprintf(NULL, 0, format, args);
#endif
va_end(args);
if (size <= 0)
return -1;
buffer = (char *)XMALLOC(size+1, 0, DYNAMIC_TYPE_OPENSSL);
if (buffer == NULL)
return -1;
XMEMSET(buffer, 0, size+1);
ret = vsnprintf(buffer, size+1, format, args2);
va_end(args2);
if (ret != size) {
XFREE(buffer, 0, DYNAMIC_TYPE_OPENSSL);
return -1;
}
ret = WOLFCRYPT_BIO_write(bio, buffer, size);
XFREE(buffer, 0, DYNAMIC_TYPE_OPENSSL);
return ret;
}
void WOLFCRYPT_BIO_copy_next_retry(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_set_flags(bio, WOLFCRYPT_BIO_get_retry_flags(bio->next_bio));
bio->retry_reason = bio->next_bio->retry_reason;
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_dup_chain(WOLFCRYPT_BIO *in)
{
WOLFCRYPT_BIO *ret = NULL, *eoc = NULL, *bio, *new_bio;
for (bio = in; bio != NULL; bio = bio->next_bio) {
new_bio = WOLFCRYPT_BIO_new(bio->method);
if (new_bio == NULL) {
goto err;
}
new_bio->callback = bio->callback;
new_bio->cb_arg = bio->cb_arg;
new_bio->init = bio->init;
new_bio->shutdown = bio->shutdown;
new_bio->flags = bio->flags;
new_bio->num = bio->num;
if (!WOLFCRYPT_BIO_dup_state(bio, new_bio)) {
WOLFCRYPT_BIO_free(new_bio);
goto err;
}
if (ret == NULL) {
eoc = new_bio;
ret = eoc;
} else {
WOLFCRYPT_BIO_push(eoc, new_bio);
eoc = new_bio;
}
}
return ret;
err:
WOLFCRYPT_BIO_free_all(ret);
return NULL;
}
#endif /* OPENSSL_EXTRA */

669
wolfcrypt/src/bio_f_b64.c Normal file
View File

@@ -0,0 +1,669 @@
/* bio_f_b64.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/coding.h>
#include <wolfssl/openssl/bio.h>
static int WOLFCRYPT_BIO_b64_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_b64_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_b64_puts(WOLFCRYPT_BIO *bio, const char *str);
static long WOLFCRYPT_BIO_b64_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_b64_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_b64_free(WOLFCRYPT_BIO *bio);
static long WOLFCRYPT_BIO_b64_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp);
#define WOLFCRYPT_B64_BLOCK_SIZE 20*48
#define WOLFCRYPT_B64_ENCODE_SIZE 20*64 + 40 // 40 : 20 CR LF
#define WOLFCRYPT_B64_NONE 0
#define WOLFCRYPT_B64_ENCODE 1
#define WOLFCRYPT_B64_DECODE 2
typedef struct {
int dataLen; /* data length */
int dataIdx; /* data index */
int workLen; /* working buffer length */
int workNl; /* used to stop when find a '\n' */
int encode; /* base64 operation */
int start; /* decoding started */
int cont; /* <= 0 when finished */
char data[WOLFCRYPT_B64_ENCODE_SIZE];
char work[WOLFCRYPT_B64_BLOCK_SIZE];
} WOLFCRYPT_BIO_F_B64_CTX;
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_b64_method = {
BIO_TYPE_BASE64,
"Base64",
WOLFCRYPT_BIO_b64_write,
WOLFCRYPT_BIO_b64_read,
WOLFCRYPT_BIO_b64_puts,
NULL, /* gets */
WOLFCRYPT_BIO_b64_ctrl,
WOLFCRYPT_BIO_b64_new,
WOLFCRYPT_BIO_b64_free,
WOLFCRYPT_BIO_b64_callback_ctrl,
};
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_base64(void)
{
return (&WOLFCRYPT_BIO_b64_method);
}
static int WOLFCRYPT_BIO_b64_new(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_F_B64_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_new");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
bio->ptr = (WOLFCRYPT_BIO_F_B64_CTX *)
XMALLOC(sizeof(WOLFCRYPT_BIO_F_B64_CTX),
0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
ctx = (WOLFCRYPT_BIO_F_B64_CTX *)bio->ptr;
ctx->dataLen = 0;
ctx->workLen = 0;
ctx->workNl = 0;
ctx->dataIdx = 0;
ctx->cont = 1;
ctx->start = 1;
ctx->encode = 0;
bio->init = 1;
bio->flags = 0;
bio->num = 0;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_new", 1);
return 1;
}
static int WOLFCRYPT_BIO_b64_free(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (bio->ptr != NULL) {
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
bio->ptr = NULL;
}
bio->init = 0;
bio->flags = 0;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_free", 1);
return 1;
}
static int WOLFCRYPT_BIO_b64_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = 0, idx, bread, j, k, num, ret_code = 0;
WOLFCRYPT_BIO_F_B64_CTX *ctx;
//unsigned char *p, *q;
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_read");
if (bio == NULL || !bio->init || bio->ptr == NULL ||
bio->next_bio == NULL || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
ctx = (WOLFCRYPT_BIO_F_B64_CTX *)bio->ptr;
/* decode when reading */
if (ctx->encode != WOLFCRYPT_B64_DECODE) {
ctx->encode = WOLFCRYPT_B64_DECODE;
ctx->dataLen = 0;
ctx->dataIdx = 0;
ctx->workLen = 0;
//WOLFCRYPT_EVP_DecodeInit(&(ctx->b64_ctx));
}
/* First check if there are bytes decoded/encoded */
if (ctx->dataLen > 0) {
if (ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_read", -1);
return -1;
}
bread = ctx->dataLen - ctx->dataIdx;
if (bread > size)
bread = size;
if (ctx->dataIdx + bread >= (int)sizeof(ctx->data)) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_read", -1);
return -1;
}
XMEMCPY(data, &(ctx->data[ctx->dataIdx]), bread);
ret = bread;
data += bread;
size -= bread;
ctx->dataIdx += bread;
if (ctx->dataLen == ctx->dataIdx) {
ctx->dataLen = 0;
ctx->dataIdx = 0;
}
}
/*
* At this point, we have room of size bytes and an empty buffer, so we
* should read in some more.
*/
ret_code = 0;
idx = 0;
while (size > 0) {
if (ctx->cont <= 0)
break;
bread = WOLFCRYPT_BIO_read(bio->next_bio, &ctx->work[ctx->workLen],
sizeof(ctx->work) - ctx->workLen);
if (bread <= 0) {
ret_code = bread;
/* Should we continue next time we are called? */
if (!WOLFCRYPT_BIO_should_retry(bio->next_bio)) {
ctx->cont = bread;
/* If buffer empty break */
if (!ctx->workLen)
break;
else
bread = 0;
}
/* else we retry and add more data to buffer */
else
break;
}
bread += ctx->workLen;
ctx->workLen = bread;
/*
* We need to scan, a line at a time until we have a valid line if we
* are starting.
*/
if (ctx->start && (WOLFCRYPT_BIO_get_flags(bio) & BIO_FLAGS_BASE64_NO_NL))
ctx->workLen = 0;
else if (ctx->start) {
/* search \n */
ctx->workNl = -1;
/* parse working buffer to find line endings */
for (j = 0; j < bread; j++) {
/* no end of line, continue */
if (ctx->work[j] != '\n')
continue;
/* we found an end of line, keep the position to
* decode the line */
ctx->workNl = j;
/* decode the line found */
num = sizeof(ctx->data) - ctx->dataIdx;
k = Base64_Decode((const byte*)ctx->work+idx,ctx->workNl-idx,
(byte *)ctx->data+ctx->dataIdx, (word32 *)&num);
if (k < 0 && !num && ctx->start) {
WOLFSSL_ERROR(BIO_B64_DECODE_E);
return -1;
}
else
ctx->start = 0;
/* +1 => skeep \n */
idx = (ctx->workNl + 1);
ctx->dataLen += num;
ctx->dataIdx += num;
}
} else if ((bread < WOLFCRYPT_B64_BLOCK_SIZE) && (ctx->cont > 0)) {
/*
* If buffer isn't full and we can retry then restart to read in
* more data.
*/
continue;
}
if (WOLFCRYPT_BIO_get_flags(bio) & BIO_FLAGS_BASE64_NO_NL) {
int z, jj;
jj = bread & ~3;
z = sizeof(ctx->data);
k = Base64_Decode((const byte*)ctx->work, jj,
(byte *)ctx->data, (word32 *)&z);
if (k < 0 || !z) {
WOLFSSL_ERROR(BIO_B64_DECODE_E);
return -1;
}
/* z is now number of output bytes and jj is the number consumed
*/
if (jj != bread) {
ctx->workLen = bread - jj;
XMEMMOVE(ctx->work, &ctx->work[jj], ctx->workLen);
}
if (z > 0)
ctx->dataLen = z;
else
ctx->dataLen = 0;
bread = z;
}
ctx->dataIdx = 0;
if (bread < 0) {
ret_code = 0;
ctx->dataLen = 0;
break;
}
if (!(WOLFCRYPT_BIO_get_flags(bio) & BIO_FLAGS_BASE64_NO_NL)) {
/* keep no parsed data in working buffer */
XMEMMOVE(ctx->work, ctx->work+idx, ctx->workLen-idx);
ctx->workLen -= idx;
idx = 0;
ctx->start = 1;
}
bread = (ctx->dataLen <= size ? ctx->dataLen : size);
XMEMCPY(data, ctx->data, bread);
ret += bread;
if (bread == ctx->dataLen) {
ctx->dataLen = 0;
ctx->dataIdx = 0;
}
else
ctx->dataIdx = bread;
size -= bread;
data += bread;
}
WOLFCRYPT_BIO_copy_next_retry(bio);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_read", (!ret ? ret_code : ret));
return (!ret ? ret_code : ret);
}
static int WOLFCRYPT_BIO_b64_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret = 0;
int n;
int i;
WOLFCRYPT_BIO_F_B64_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_write");
if (bio == NULL || !bio->init || bio->ptr == NULL ||
bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
ctx = (WOLFCRYPT_BIO_F_B64_CTX *)bio->ptr;
/* encode when writing */
if (ctx->encode != WOLFCRYPT_B64_ENCODE) {
ctx->encode = WOLFCRYPT_B64_ENCODE;
ctx->dataLen = 0;
ctx->dataIdx = 0;
ctx->workLen = 0;
}
if (ctx->dataIdx >= (int)sizeof(ctx->data) ||
ctx->dataLen > (int)sizeof(ctx->data) ||
ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
n = ctx->dataLen - ctx->dataIdx;
while (n > 0) {
i = WOLFCRYPT_BIO_write(bio->next_bio, &ctx->data[ctx->dataIdx], n);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
return i;
}
/* mustn't appen, just to be sure */
if (i > n) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
ctx->dataIdx += i;
n -= i;
if (ctx->dataIdx > (int)sizeof(ctx->data) ||
ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
}
/* at this point all pending data has been written */
ctx->dataIdx = 0;
ctx->dataLen = 0;
if (data == NULL || size <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
while (size > 0) {
n = (size > WOLFCRYPT_B64_BLOCK_SIZE) ? WOLFCRYPT_B64_BLOCK_SIZE : size;
if (ctx->workLen > 0) {
if (ctx->workLen > WOLFCRYPT_B64_BLOCK_SIZE) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
n = WOLFCRYPT_B64_BLOCK_SIZE - ctx->workLen;
if (n > size)
n = size;
XMEMCPY(&ctx->work[ctx->workLen], data, n);
ctx->workLen += n;
ret += n;
if (ctx->workLen < WOLFCRYPT_B64_BLOCK_SIZE)
break;
ctx->dataLen = sizeof(ctx->data);
if (WOLFCRYPT_BIO_get_flags(bio) & BIO_FLAGS_BASE64_NO_NL)
Base64_Encode_NoNl((const byte *)ctx->work, ctx->workLen,
(byte *)ctx->data,
(word32 *)&ctx->dataLen);
else
Base64_Encode((const byte *)ctx->work, ctx->workLen,
(byte *)ctx->data, (word32 *)&ctx->dataLen);
if (ctx->dataLen > (int)sizeof(ctx->data) ||
ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
ctx->workLen = 0;
}
else {
/* keep data and wait for more before encoding */
if (n < WOLFCRYPT_B64_BLOCK_SIZE) {
XMEMCPY(ctx->work, data, n);
ctx->workLen = n;
ret += n;
break;
}
n -= n % WOLFCRYPT_B64_BLOCK_SIZE;
ctx->dataLen = sizeof(ctx->data);
if (WOLFCRYPT_BIO_get_flags(bio) & BIO_FLAGS_BASE64_NO_NL)
Base64_Encode_NoNl((const byte *)data, n,
(byte *)ctx->data,
(word32 *)&ctx->dataLen);
else
Base64_Encode((const byte *)data, n,
(byte *)ctx->data, (word32 *)&ctx->dataLen);
if (ctx->dataLen > (int)sizeof(ctx->data) ||
ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
ret += n;
}
size -= n;
data += n;
ctx->dataIdx = 0;
n = ctx->dataLen;
while (n > 0) {
i = WOLFCRYPT_BIO_write(bio->next_bio,
&(ctx->data[ctx->dataIdx]), n);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", !ret ? i : ret);
return (!ret ? i : ret);
}
if (i > n) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
n -= i;
ctx->dataIdx += i;
if (ctx->dataLen > (int)sizeof(ctx->data) ||
ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
}
ctx->dataLen = 0;
ctx->dataIdx = 0;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", ret);
return ret;
}
static long WOLFCRYPT_BIO_b64_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
WOLFCRYPT_BIO_F_B64_CTX *ctx;
long ret = 1;
int i;
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_ctrl");
if (bio == NULL || bio->ptr == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFCRYPT_BIO_F_B64_CTX *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ctx->cont = 1;
ctx->start = 1;
ctx->encode = WOLFCRYPT_B64_NONE;
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_EOF:
ret = (ctx->cont <= 0 ? 1 :
WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr));
break;
case BIO_CTRL_WPENDING:
if (ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
ret = ctx->dataLen - ctx->dataIdx;
if (!ret && (ctx->encode != WOLFCRYPT_B64_NONE) &&
(ctx->workLen != 0))
ret = 1;
else if (ret <= 0)
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_PENDING:
if (ctx->dataLen < ctx->dataIdx) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
ret = ctx->dataLen - ctx->dataIdx;
if (ret <= 0)
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_FLUSH:
/* do a final write */
again:
while (ctx->dataLen != ctx->dataIdx) {
i = WOLFCRYPT_BIO_b64_write(bio, NULL, 0);
if (i < 0)
return i;
}
if (ctx->workLen != 0) {
ctx->dataLen = sizeof(ctx->data);
if (WOLFCRYPT_BIO_get_flags(bio) & BIO_FLAGS_BASE64_NO_NL)
Base64_Encode_NoNl((const byte *)ctx->work, ctx->workLen,
(byte *)ctx->data,
(word32 *)&ctx->dataLen);
else {
Base64_Encode((const byte *)ctx->work, ctx->workLen,
(byte *)ctx->data, (word32 *)&ctx->dataLen);
if (ctx->dataLen > (int)sizeof(ctx->data)) {
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_write", -1);
return -1;
}
}
ctx->dataIdx = 0;
ctx->workLen = 0;
goto again;
}
/* Finally flush the underlying BIO */
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_C_DO_STATE_MACHINE:
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
WOLFCRYPT_BIO_copy_next_retry(bio);
break;
case BIO_CTRL_DUP:
break;
case BIO_CTRL_INFO:
case BIO_CTRL_GET:
case BIO_CTRL_SET:
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
default:
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_b64_ctrl", (int)ret);
return ret;
}
static long WOLFCRYPT_BIO_b64_callback_ctrl(WOLFCRYPT_BIO *bio,
int cmd, WOLFCRYPT_BIO_info_cb *fp)
{
if (bio == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_callback_ctrl");
return WOLFCRYPT_BIO_callback_ctrl(bio->next_bio, cmd, fp);
}
static int WOLFCRYPT_BIO_b64_puts(WOLFCRYPT_BIO *bio, const char *str)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_b64_puts");
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
return WOLFCRYPT_BIO_b64_write(bio, str, (int)strlen(str));
}
#endif /* OPENSSL_EXTRA */

583
wolfcrypt/src/bio_f_buff.c Normal file
View File

@@ -0,0 +1,583 @@
/* bio_f_buff.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/openssl/bio.h>
typedef struct {
/*-
* Buffers are setup like this:
*
* <---------------------- size ----------------------->
* +---------------------------------------------------+
* | consumed | remaining | free space |
* +---------------------------------------------------+
* <-- off --><------- len ------->
*/
/* input buffer */
char *in; /* the char array */
int inSz; /* how big is the input buffer */
int inLen; /* how many bytes are in it */
int inIdx; /* write/read offset */
/* output buffer */
char *out; /* the char array */
int outSz; /* how big is the output buffer */
int outLen; /* how many bytes are in it */
int outIdx; /* write/read offset */
} WOLFCRYPT_BIO_F_BUFFER_CTX;
/* OpenSSL default value */
#define WOLFSSL_F_BUFFER_SIZE_DEFAULT 4096
static int WOLFCRYPT_BIO_buffer_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_buffer_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_buffer_puts(WOLFCRYPT_BIO *bio, const char *str);
static int WOLFCRYPT_BIO_buffer_gets(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_buffer_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_buffer_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_buffer_free(WOLFCRYPT_BIO *bio);
static long WOLFCRYPT_BIO_buffer_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_buffer_method = {
BIO_TYPE_BUFFER,
"Buffer",
WOLFCRYPT_BIO_buffer_write,
WOLFCRYPT_BIO_buffer_read,
WOLFCRYPT_BIO_buffer_puts,
WOLFCRYPT_BIO_buffer_gets,
WOLFCRYPT_BIO_buffer_ctrl,
WOLFCRYPT_BIO_buffer_new,
WOLFCRYPT_BIO_buffer_free,
WOLFCRYPT_BIO_buffer_callback_ctrl,
};
static long WOLFCRYPT_BIO_buffer_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp)
{
if (bio == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
return WOLFCRYPT_BIO_callback_ctrl(bio->next_bio, cmd, fp);
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_buffer(void)
{
return (&WOLFCRYPT_BIO_buffer_method);
}
static int WOLFCRYPT_BIO_buffer_new(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_F_BUFFER_CTX *ctx;
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
bio->ptr = (WOLFCRYPT_BIO_F_BUFFER_CTX *)
XMALLOC(sizeof(WOLFCRYPT_BIO_F_BUFFER_CTX),
0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
ctx = (WOLFCRYPT_BIO_F_BUFFER_CTX *)bio->ptr;
ctx->in = (char *)XMALLOC(WOLFSSL_F_BUFFER_SIZE_DEFAULT, 0,
DYNAMIC_TYPE_OPENSSL);
if (ctx->in == NULL) {
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
ctx->out = (char *)XMALLOC(WOLFSSL_F_BUFFER_SIZE_DEFAULT, 0,
DYNAMIC_TYPE_OPENSSL);
if (ctx->out == NULL) {
XFREE(ctx->in, 0, DYNAMIC_TYPE_OPENSSL);
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
ctx->inSz = WOLFSSL_F_BUFFER_SIZE_DEFAULT;
ctx->inLen = 0;
ctx->inIdx = 0;
ctx->outSz = WOLFSSL_F_BUFFER_SIZE_DEFAULT;
ctx->outLen = 0;
ctx->outIdx = 0;
bio->init = 1;
bio->flags = 0;
return 1;
}
static int WOLFCRYPT_BIO_buffer_free(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_F_BUFFER_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_buffer_free");
if (bio == NULL)
return 0;
if (!bio->init || bio->ptr == NULL)
return 1;
ctx = (WOLFCRYPT_BIO_F_BUFFER_CTX *)bio->ptr;
if (ctx->in != NULL) {
XFREE(ctx->in, 0, DYNAMIC_TYPE_OPENSSL);
ctx->in = NULL;
}
if (ctx->out != NULL) {
XFREE(ctx->out, 0, DYNAMIC_TYPE_OPENSSL);
ctx->out = NULL;
}
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
bio->ptr = NULL;
bio->init = 0;
bio->flags = 0;
return 1;
}
static int WOLFCRYPT_BIO_buffer_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int i, num = 0;
WOLFCRYPT_BIO_F_BUFFER_CTX *ctx;
if (bio == NULL || !bio->init ||
bio->ptr == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
ctx = (WOLFCRYPT_BIO_F_BUFFER_CTX *)bio->ptr;
for (;;) {
i = ctx->inLen;
if (i != 0) {
if (i > size)
i = size;
XMEMCPY(data, &(ctx->in[ctx->inIdx]), i);
ctx->inIdx += i;
ctx->inLen -= i;
num += i;
if (size == i)
return num;
size -= i;
data += i;
}
/* case of partial read */
if (size > ctx->inSz) {
for (;;) {
i = WOLFCRYPT_BIO_read(bio->next_bio, data, size);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
if (i < 0)
return (num > 0 ? num : i);
else if (i == 0)
return num;
}
num += i;
if (size == i)
return num;
data += i;
size -= i;
}
}
/* we are going to be doing some buffering */
i = WOLFCRYPT_BIO_read(bio->next_bio, ctx->in, ctx->inSz);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
if (i < 0)
return (num > 0 ? num : i);
if (i == 0)
return num;
}
ctx->inIdx = 0;
ctx->inLen = i;
}
return 1;
}
static int WOLFCRYPT_BIO_buffer_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int i, num = 0;
WOLFCRYPT_BIO_F_BUFFER_CTX *ctx;
if (bio == NULL || !bio->init || bio->ptr == NULL ||
bio->next_bio == NULL || size <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
ctx = (WOLFCRYPT_BIO_F_BUFFER_CTX *)bio->ptr;
for (;;) {
i = ctx->outSz - (ctx->outLen + ctx->outIdx);
/* add to buffer and return */
if (i >= size) {
XMEMCPY(&(ctx->out[ctx->outIdx + ctx->outLen]), data, size);
ctx->outLen += size;
return (num + size);
}
/* stuff already in buffer, so add to it first, then flush */
if (ctx->outLen != 0) {
if (i > 0) {
XMEMCPY(&(ctx->out[ctx->outIdx + ctx->outLen]), data, i);
data += i;
size -= i;
num += i;
ctx->outLen += i;
}
/* we now have a full buffer needing flushing */
do {
i = WOLFCRYPT_BIO_write(bio->next_bio,
&(ctx->out[ctx->outIdx]), ctx->outLen);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
if (i < 0)
return (num > 0 ? num : i);
if (i == 0)
return num;
}
ctx->outIdx += i;
ctx->outLen -= i;
} while (ctx->outLen != 0);
}
ctx->outIdx = 0;
/* we now have size bytes to write */
while (size >= ctx->outSz) {
i = WOLFCRYPT_BIO_write(bio->next_bio, data, size);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
if (i < 0)
return (num > 0 ? num : i);
if (i == 0)
return num;
}
num += i;
data += i;
size -= i;
if (size == 0)
return num;
}
}
return 1;
}
static long WOLFCRYPT_BIO_buffer_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
int i, *ip, ibs, obs;
long ret = 1;
WOLFCRYPT_BIO_F_BUFFER_CTX *ctx;
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFCRYPT_BIO_F_BUFFER_CTX *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ctx->inLen = 0;
ctx->inIdx = 0;
ctx->outLen = 0;
ctx->outIdx = 0;
if (bio->next_bio == NULL)
return 0;
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_INFO:
ret = (long)ctx->outLen;
break;
case BIO_C_GET_BUFF_NUM_LINES:
ret = 0;
for (i = 0; i < ctx->inLen; i++) {
if (ctx->in[ctx->inIdx + i] == '\n')
ret++;
}
break;
case BIO_CTRL_WPENDING:
ret = (long)ctx->outLen;
if (ret == 0) {
if (bio->next_bio == NULL)
return 0;
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
}
break;
case BIO_CTRL_PENDING:
ret = (long)ctx->inLen;
if (ret == 0) {
if (bio->next_bio == NULL)
return 0;
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
}
break;
case BIO_C_SET_BUFF_READ_DATA:
if (num > ctx->inSz) {
ctx->in = XREALLOC(ctx->in, num, 0, DYNAMIC_TYPE_OPENSSL);
if (ctx->in == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
}
ctx->inIdx = 0;
ctx->inLen = (int)num;
XMEMCPY(ctx->in, ptr, num);
ret = 1;
break;
case BIO_C_SET_BUFF_SIZE:
if (ptr != NULL) {
ip = (int *)ptr;
if (*ip == 0) {
ibs = (int)num;
obs = ctx->outSz;
} else {
ibs = ctx->inSz;
obs = (int)num;
}
} else {
ibs = (int)num;
obs = (int)num;
}
if ((ibs > WOLFSSL_F_BUFFER_SIZE_DEFAULT) && (ibs != ctx->inSz)) {
ctx->in = XREALLOC(ctx->in, num, 0, DYNAMIC_TYPE_OPENSSL);
if (ctx->in == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
ctx->inIdx = 0;
ctx->inLen = 0;
ctx->inSz = ibs;
}
if ((obs > WOLFSSL_F_BUFFER_SIZE_DEFAULT) && (obs != ctx->outSz)) {
ctx->out = XREALLOC(ctx->out, num, 0, DYNAMIC_TYPE_OPENSSL);
if (ctx->out == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
ctx->outIdx = 0;
ctx->outLen = 0;
ctx->outSz = obs;
}
break;
case BIO_C_DO_STATE_MACHINE:
if (bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
WOLFCRYPT_BIO_copy_next_retry(bio);
break;
case BIO_CTRL_FLUSH:
if (bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (ctx->outLen <= 0) {
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
}
for (;;) {
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ctx->outLen > 0) {
ret = WOLFCRYPT_BIO_write(bio->next_bio,
&(ctx->out[ctx->outIdx]), ctx->outLen);
WOLFCRYPT_BIO_copy_next_retry(bio);
if (ret <= 0)
return ret;
ctx->outIdx += ret;
ctx->outLen -= ret;
} else {
ctx->outLen = 0;
ctx->outIdx = 0;
ret = 1;
break;
}
}
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_DUP:
ret = WOLFCRYPT_BIO_set_read_buffer_size((WOLFCRYPT_BIO *)ptr,
ctx->inSz);
if (!ret)
break;
ret = WOLFCRYPT_BIO_set_write_buffer_size((WOLFCRYPT_BIO *)ptr,
ctx->outSz);
if (!ret)
break;
ret = 1;
break;
default:
if (bio->next_bio == NULL)
return 0;
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
}
return ret;
}
static int WOLFCRYPT_BIO_buffer_gets(WOLFCRYPT_BIO *bio, char *buf, int size)
{
WOLFCRYPT_BIO_F_BUFFER_CTX *ctx;
int num = 0, i, flag;
if (bio == NULL || bio->ptr == NULL || buf == NULL || size <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
ctx = (WOLFCRYPT_BIO_F_BUFFER_CTX *)bio->ptr;
/* to put end of string */
size--;
for (;;) {
if (ctx->inLen > 0) {
// p = &(ctx->in[ctx->inIdx]);
flag = 0;
for (i = 0; (i < ctx->inLen) && (i < size); i++) {
*(buf++) = ctx->in[ctx->inIdx+i];
if (ctx->in[ctx->inIdx+i] == '\n') {
flag = 1;
i++;
break;
}
}
num += i;
size -= i;
ctx->inLen -= i;
ctx->inIdx += i;
if (flag || !size) {
*buf = '\0';
return num;
}
} else {
i = WOLFCRYPT_BIO_read(bio->next_bio, ctx->in, ctx->inSz);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
*buf = '\0';
if (i < 0)
return (num > 0 ? num : i);
if (i == 0)
return num;
}
ctx->inLen = i;
ctx->inIdx = 0;
}
}
return i;
}
static int WOLFCRYPT_BIO_buffer_puts(WOLFCRYPT_BIO *bio, const char *str)
{
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
return WOLFCRYPT_BIO_buffer_write(bio, str, (int)strlen(str));
}
#endif /* OPENSSL_EXTRA */

View File

@@ -0,0 +1,456 @@
/* bio_f_cipher.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/openssl/evp.h>
#include <wolfssl/openssl/bio.h>
typedef struct {
int dataLen;
int dataIdx;
int cont;
int finished;
int ok; /* bad decrypt */
WOLFSSL_EVP_CIPHER_CTX cipher;
/*
* buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return
* up to a block more data than is presented to it
*/
#define WOLFCRYPT_ENC_BLOCK_SIZE 128
#define WOLFCRYPT_BUF_OFFSET 64
byte data[WOLFCRYPT_ENC_BLOCK_SIZE + WOLFCRYPT_BUF_OFFSET + 2];
} WOLFCRYPT_BIO_ENC_CTX;
static int WOLFCRYPT_BIO_cipher_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_cipher_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_cipher_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_cipher_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_cipher_free(WOLFCRYPT_BIO *bio);
static long WOLFCRYPT_BIO_cipher_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_cipher_method = {
BIO_TYPE_CIPHER,
"Cipher",
WOLFCRYPT_BIO_cipher_write,
WOLFCRYPT_BIO_cipher_read,
NULL, /* puts */
NULL, /* gets */
WOLFCRYPT_BIO_cipher_ctrl,
WOLFCRYPT_BIO_cipher_new,
WOLFCRYPT_BIO_cipher_free,
WOLFCRYPT_BIO_cipher_callback_ctrl,
};
static long WOLFCRYPT_BIO_cipher_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_cipher_callback_ctrl");
if (bio == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
return WOLFCRYPT_BIO_callback_ctrl(bio->next_bio, cmd, fp);
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_cipher(void)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_f_cipher");
return (&WOLFCRYPT_BIO_cipher_method);
}
void WOLFCRYPT_BIO_set_cipher(WOLFCRYPT_BIO *bio,
const WOLFSSL_EVP_CIPHER *cipher,
const unsigned char *key,
const unsigned char *iv, int enc)
{
WOLFCRYPT_BIO_ENC_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_set_cipher");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return;
}
if ((bio->callback != NULL) &&
bio->callback(bio, BIO_CB_CTRL, (const char *)cipher,
BIO_CTRL_SET, enc, 0) <= 0) {
WOLFSSL_ERROR(BIO_CALLBACK_E);
return;
}
bio->init = 1;
ctx = (WOLFCRYPT_BIO_ENC_CTX *)bio->ptr;
wolfSSL_EVP_CipherInit(&(ctx->cipher), cipher, (unsigned char *)key,
(unsigned char *)iv, enc);
if ((bio->callback != NULL) &&
bio->callback(bio, BIO_CB_CTRL, (const char *)cipher,
BIO_CTRL_SET, enc, 1) <= 0)
WOLFSSL_ERROR(BIO_CALLBACK_E);
}
static int WOLFCRYPT_BIO_cipher_new(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_ENC_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_cipher_new");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bio->ptr = (WOLFCRYPT_BIO_ENC_CTX *)XMALLOC(sizeof(WOLFCRYPT_BIO_ENC_CTX),
0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return -1;
}
ctx = (WOLFCRYPT_BIO_ENC_CTX *)bio->ptr;
wolfSSL_EVP_CIPHER_CTX_init(&ctx->cipher);
ctx->dataLen = 0;
ctx->dataIdx = 0;
ctx->cont = 1;
ctx->finished = 0;
ctx->ok = 1;
bio->init = 0;
bio->flags = 0;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_cipher_new", 1);
return 1;
}
static int WOLFCRYPT_BIO_cipher_free(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_ENC_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_cipher_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFCRYPT_BIO_ENC_CTX *)bio->ptr;
wolfSSL_EVP_CIPHER_CTX_cleanup(&(ctx->cipher));
XMEMSET(bio->ptr, 0, sizeof(WOLFCRYPT_BIO_ENC_CTX));
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
bio->ptr = NULL;
bio->init = 0;
bio->flags = 0;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_cipher_free", 1);
return 1;
}
static int WOLFCRYPT_BIO_cipher_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = 0, i;
WOLFCRYPT_BIO_ENC_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_cipher_read");
if (bio == NULL || data == NULL ||
bio->ptr == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFCRYPT_BIO_ENC_CTX *)bio->ptr;
/* First check if there are bytes decoded/encoded */
if (ctx->dataLen > 0) {
i = ctx->dataLen - ctx->dataIdx;
if (i > size)
i = size;
XMEMCPY(data, &ctx->data[ctx->dataIdx], i);
ret = i;
data += i;
size -= i;
ctx->dataIdx += i;
/* all read */
if (ctx->dataLen == ctx->dataIdx)
ctx->dataLen = ctx->dataIdx = 0;
}
/*
* At this point, we have room of size bytes and an empty buffer, so we
* should read in some more.
*/
while (size > 0) {
if (ctx->cont <= 0)
break;
/* read in at IV offset, read the EVP_Cipher documentation about why
*/
i = WOLFCRYPT_BIO_read(bio->next_bio, &ctx->data[WOLFCRYPT_BUF_OFFSET],
WOLFCRYPT_ENC_BLOCK_SIZE);
if (i <= 0) {
/* Should be continue next time we are called ? */
if (!WOLFCRYPT_BIO_should_retry(bio->next_bio)) {
ctx->cont = i;
i = wolfSSL_EVP_CipherFinal(&ctx->cipher, ctx->data,
&ctx->dataLen);
ctx->ok = i;
ctx->dataIdx = 0;
} else {
if (!ret)
ret = i;
break;
}
} else {
wolfSSL_EVP_CipherUpdate(&ctx->cipher,
ctx->data, &ctx->dataLen,
&ctx->data[WOLFCRYPT_BUF_OFFSET], i);
ctx->cont = 1;
if (!ctx->dataLen)
continue;
}
i = (ctx->dataLen <= size ? ctx->dataLen : size);
if (i <= 0)
break;
XMEMCPY(data, ctx->data, i);
ret += i;
ctx->dataIdx = i;
size -= i;
data += i;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
WOLFCRYPT_BIO_copy_next_retry(bio);
return (!ret ? ctx->cont : ret);
}
static int WOLFCRYPT_BIO_cipher_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret, n, i;
WOLFCRYPT_BIO_ENC_CTX *ctx;
WOLFSSL_ENTER("WOLFCRYPT_BIO_cipher_write");
if (bio == NULL || bio->ptr == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
ctx = (WOLFCRYPT_BIO_ENC_CTX *)bio->ptr;
ret = size;
WOLFCRYPT_BIO_clear_retry_flags(bio);
n = ctx->dataLen - ctx->dataIdx;
while (n > 0) {
i = WOLFCRYPT_BIO_write(bio->next_bio, &ctx->data[ctx->dataIdx], n);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
return i;
}
ctx->dataIdx += i;
n -= i;
}
/* at this point all pending data has been written
* return if we haven't new data to write */
if (data == NULL || size <= 0)
return 0;
while (size > 0) {
n = (size > WOLFCRYPT_ENC_BLOCK_SIZE ? WOLFCRYPT_ENC_BLOCK_SIZE : size);
wolfSSL_EVP_CipherUpdate(&ctx->cipher, ctx->data, &ctx->dataLen,
(byte *)data, n);
size -= n;
data += n;
ctx->dataIdx = 0;
n = ctx->dataLen;
while (n > 0) {
i = WOLFCRYPT_BIO_write(bio->next_bio,
&ctx->data[ctx->dataIdx], n);
if (i <= 0) {
WOLFCRYPT_BIO_copy_next_retry(bio);
return (ret == size ? i : ret - size);
}
n -= i;
ctx->dataIdx += i;
}
ctx->dataLen = 0;
ctx->dataIdx = 0;
}
WOLFCRYPT_BIO_copy_next_retry(bio);
return ret;
}
static long WOLFCRYPT_BIO_cipher_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr)
{
WOLFCRYPT_BIO_ENC_CTX *ctx;
long ret = 1;
int i;
WOLFSSL_ENTER("WOLFCRYPT_BIO_cipher_ctrl");
if (bio == NULL || bio->ptr == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
ctx = (WOLFCRYPT_BIO_ENC_CTX *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ctx->ok = 1;
ctx->finished = 0;
wolfSSL_EVP_CipherInit(&ctx->cipher, NULL, NULL, NULL,
ctx->cipher.enc);
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_EOF: /* More to read */
if (ctx->cont <= 0)
ret = 1;
else
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_WPENDING:
case BIO_CTRL_PENDING:
ret = ctx->dataLen - ctx->dataIdx;
if (ret <= 0)
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_CTRL_FLUSH:
loop:
while (ctx->dataLen != ctx->dataIdx) {
i = WOLFCRYPT_BIO_cipher_write(bio, NULL, 0);
if (i < 0)
return i;
}
if (!ctx->finished) {
ctx->finished = 1;
ctx->dataIdx = 0;
ret = wolfSSL_EVP_CipherFinal(&ctx->cipher, ctx->data,
&ctx->dataLen);
ctx->ok = (int)ret;
if (ret <= 0)
break;
goto loop;
}
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_C_GET_CIPHER_STATUS:
ret = (long)ctx->ok;
break;
case BIO_C_DO_STATE_MACHINE:
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
WOLFCRYPT_BIO_copy_next_retry(bio);
break;
case BIO_C_GET_CIPHER_CTX:
{
WOLFSSL_EVP_CIPHER_CTX **c_ctx;
c_ctx = (WOLFSSL_EVP_CIPHER_CTX **)ptr;
*c_ctx = &ctx->cipher;
bio->init = 1;
}
break;
case BIO_CTRL_DUP:
{
WOLFCRYPT_BIO *dbio;
WOLFCRYPT_BIO_ENC_CTX *dctx;
dbio = (WOLFCRYPT_BIO *)ptr;
dctx = (WOLFCRYPT_BIO_ENC_CTX *)dbio->ptr;
wolfSSL_EVP_CIPHER_CTX_init(&dctx->cipher);
ret = wolfSSL_EVP_CIPHER_CTX_copy(&dctx->cipher, &ctx->cipher);
if (ret)
dbio->init = 1;
}
break;
default:
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_cipher_ctrl", (int)ret);
return ret;
}
#endif /* OPENSSL_EXTRA */

311
wolfcrypt/src/bio_f_dgst.c Normal file
View File

@@ -0,0 +1,311 @@
/* bio_f_dgst.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/openssl/evp.h>
#include <wolfssl/openssl/bio.h>
static int WOLFCRYPT_BIO_digest_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_digest_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_digest_gets(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_digest_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_digest_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_digest_free(WOLFCRYPT_BIO *bio);
static long WOLFCRYPT_BIO_digest_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_digest_method = {
BIO_TYPE_MD,
"Message digest",
WOLFCRYPT_BIO_digest_write,
WOLFCRYPT_BIO_digest_read,
NULL, /* puts */
WOLFCRYPT_BIO_digest_gets,
WOLFCRYPT_BIO_digest_ctrl,
WOLFCRYPT_BIO_digest_new,
WOLFCRYPT_BIO_digest_free,
WOLFCRYPT_BIO_digest_callback_ctrl,
};
static long WOLFCRYPT_BIO_digest_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_callback_ctrl");
if (bio == NULL || bio->next_bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
return WOLFCRYPT_BIO_callback_ctrl(bio->next_bio, cmd, fp);
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_md(void)
{
return (&WOLFCRYPT_BIO_digest_method);
}
static int WOLFCRYPT_BIO_digest_new(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_new");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bio->ptr = (WOLFSSL_EVP_MD_CTX *)XMALLOC(sizeof(WOLFSSL_EVP_MD_CTX),
0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return -1;
}
wolfSSL_EVP_MD_CTX_init((WOLFSSL_EVP_MD_CTX *)bio->ptr);
bio->init = 0;
bio->flags = 0;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_digest_new", 1);
return 1;
}
static int WOLFCRYPT_BIO_digest_free(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
wolfSSL_EVP_MD_CTX_cleanup((WOLFSSL_EVP_MD_CTX *)bio->ptr);
XMEMSET(bio->ptr, 0, sizeof(WOLFSSL_EVP_MD_CTX));
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
bio->ptr = NULL;
bio->init = 0;
bio->flags = 0;
WOLFSSL_LEAVE("WOLFCRYPT_BIO_digest_free", 1);
return 1;
}
static int WOLFCRYPT_BIO_digest_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
WOLFSSL_EVP_MD_CTX *ctx;
int ret = 0;
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_read");
if (bio == NULL || bio->ptr == NULL || bio->next_bio == NULL ||
data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFSSL_EVP_MD_CTX *)bio->ptr;
ret = WOLFCRYPT_BIO_read(bio->next_bio, data, size);
if (bio->init && ret > 0) {
if (wolfSSL_EVP_DigestUpdate(ctx, data, (word32)ret) != SSL_SUCCESS) {
WOLFSSL_ERROR(BIO_DGST_UPDATE_E);
return -1;
}
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
WOLFCRYPT_BIO_copy_next_retry(bio);
WOLFSSL_LEAVE("WOLFCRYPT_BIO_digest_read", ret);
return ret;
}
static int WOLFCRYPT_BIO_digest_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
WOLFSSL_EVP_MD_CTX *ctx;
int ret = 0;
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_write");
if (bio == NULL || bio->ptr == NULL || data == NULL || size <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFSSL_EVP_MD_CTX *)bio->ptr;
ret = WOLFCRYPT_BIO_write(bio->next_bio, data, size);
if (bio->init && ret > 0) {
if (wolfSSL_EVP_DigestUpdate(ctx, data, (word32)ret) != SSL_SUCCESS) {
WOLFSSL_ERROR(BIO_DGST_UPDATE_E);
WOLFCRYPT_BIO_clear_retry_flags(bio);
return -1;
}
}
if (bio->next_bio != NULL) {
WOLFCRYPT_BIO_clear_retry_flags(bio);
WOLFCRYPT_BIO_copy_next_retry(bio);
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_digest_write", ret);
return ret;
}
static long WOLFCRYPT_BIO_digest_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
WOLFSSL_EVP_MD_CTX *ctx;
long ret = 1;
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_ctrl");
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
ctx = (WOLFSSL_EVP_MD_CTX *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
if (bio->init)
ret = wolfSSL_EVP_DigestInit(ctx, ctx->digest);
else
ret = 0;
if (ret > 0)
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
case BIO_C_GET_MD:
if (bio->init) {
const WOLFSSL_EVP_MD **pmd;
pmd = (const WOLFSSL_EVP_MD **)ptr;
*pmd = ctx->digest;
} else
ret = 0;
break;
case BIO_C_GET_MD_CTX:
{
WOLFSSL_EVP_MD_CTX **pctx;
pctx = (WOLFSSL_EVP_MD_CTX **)ptr;
*pctx = ctx;
}
bio->init = 1;
break;
case BIO_C_SET_MD_CTX:
if (bio->init)
bio->ptr = ptr;
else
ret = 0;
break;
case BIO_C_DO_STATE_MACHINE:
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
WOLFCRYPT_BIO_copy_next_retry(bio);
break;
case BIO_C_SET_MD:
ret = wolfSSL_EVP_DigestInit(ctx, (WOLFSSL_EVP_MD *)ptr);
if (ret > 0)
bio->init = 1;
else
WOLFSSL_ERROR(BIO_DGST_INIT_E);
break;
case BIO_CTRL_DUP:
{
WOLFCRYPT_BIO *dbio;
WOLFSSL_EVP_MD_CTX *dctx;
dbio = (WOLFCRYPT_BIO *)ptr;
dctx = (WOLFSSL_EVP_MD_CTX *)dbio->ptr;
ret = wolfSSL_EVP_MD_CTX_copy(dctx, ctx);
if (ret)
bio->init = 1;
}
break;
default:
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
break;
}
WOLFSSL_LEAVE("WOLFCRYPT_BIO_digest_ctrl", (int)ret);
return ret;
}
static int WOLFCRYPT_BIO_digest_gets(WOLFCRYPT_BIO *bio, char *buf, int size)
{
WOLFSSL_EVP_MD_CTX *ctx;
unsigned int dgstLen = 0;
WOLFSSL_ENTER("WOLFCRYPT_BIO_digest_gets");
if (bio == NULL || bio->ptr == NULL || buf == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
ctx = (WOLFSSL_EVP_MD_CTX *)bio->ptr;
if (size < ctx->macSize) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (wolfSSL_EVP_DigestFinal(ctx, (byte *)buf, &dgstLen) != SSL_SUCCESS) {
WOLFSSL_ERROR(BIO_DGST_FINAL_E);
return -1;
}
return dgstLen;
}
#endif /* OPENSSL_EXTRA */

484
wolfcrypt/src/bio_f_sock.c Normal file
View File

@@ -0,0 +1,484 @@
/* bio_m_conn.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#ifdef USE_WINDOWS_API
#include <winsock2.h>
#include <process.h>
#else
#include <fcntl.h>
#include <netdb.h>
#ifdef SO_NOSIGPIPE
#include <signal.h>
#endif
#endif /* USE_WINDOWS_API */
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
/* Socket Handling */
#ifndef WOLFSSL_SOCKET_INVALID
#ifdef USE_WINDOWS_API
#define WOLFSSL_SOCKET_INVALID ((SOCKET)INVALID_SOCKET)
#else
#define WOLFSSL_SOCKET_INVALID (0)
#endif
#endif /* WOLFSSL_SOCKET_INVALID */
#define MAX_LISTEN 32
#ifdef USE_WINDOWS_API
static int wsa_init_done = 0;
#endif
int WOLFCRYPT_BIO_get_host_ip(const char *str, unsigned char *ip)
{
struct hostent *he;
unsigned int iip[4];
if (WOLFCRYPT_BIO_sock_init() != 1)
return 0;
/* IP found */
if (sscanf(str, "%d.%d.%d.%d", &iip[0], &iip[1], &iip[2], &iip[3]) == 4)
{
ip[0] = (iip[0] & 0xff000000) >> 24;
ip[1] = (iip[1] & 0x00ff0000) >> 16;
ip[2] = (iip[2] & 0x0000ff00) >> 8;
ip[3] = (iip[3] & 0x000000ff);
return 1;
}
/* IP not found, check with a gethostbyname */
he = gethostbyname(str);
if (he == NULL) {
WOLFSSL_ERROR(BIO_NO_HOSTNAME_E);
return 0;
}
if (he->h_addrtype != AF_INET) {
WOLFSSL_ERROR(BIO_ADDR_AF_INET_E);
return 0;
}
XMEMCPY(ip, he->h_addr_list[0], 4);
return 1;
}
int WOLFCRYPT_BIO_get_port(const char *str, unsigned short *port_ptr)
{
int i;
struct servent *s;
if (str == NULL) {
WOLFSSL_ERROR(BIO_NO_PORT_E);
return 0;
}
i = atoi(str);
if (i != 0) {
*port_ptr = (unsigned short)i;
return 1;
}
s = getservbyname(str, "tcp");
if (s != NULL) {
*port_ptr = ntohs((unsigned short)s->s_port);
return 1;
}
if (strcmp(str, "http") == 0)
*port_ptr = 80;
else if (strcmp(str, "telnet") == 0)
*port_ptr = 23;
else if (strcmp(str, "socks") == 0)
*port_ptr = 1080;
else if (strcmp(str, "https") == 0)
*port_ptr = 443;
else if (strcmp(str, "ssl") == 0)
*port_ptr = 443;
else if (strcmp(str, "ftp") == 0)
*port_ptr = 21;
else if (strcmp(str, "gopher") == 0)
*port_ptr = 70;
else {
WOLFSSL_ERROR(BIO_SRV_PROTO_E);
return 0;
}
return 1;
}
int WOLFCRYPT_BIO_sock_error(int sock)
{
int j = 0, i;
union {
size_t s;
int i;
} size;
/* heuristic way to adapt for platforms that expect 64-bit optlen */
size.s = 0, size.i = sizeof(j);
/*
* Note: under Windows the third parameter is of type (char *) whereas
* under other systems it is (void *) if you don't have a cast it will
* choke the compiler: if you do have a cast then you can either go for
* (char *) or (void *).
*/
i = getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *)&j, (void *)&size);
if (i < 0)
return 1;
return j;
}
int WOLFCRYPT_BIO_sock_init(void)
{
# ifdef USE_WINDOWS_API
static struct WSAData wsa_state;
if (!wsa_init_done) {
int err;
wsa_init_done = 1;
memset(&wsa_state, 0, sizeof(wsa_state));
/*
* Not making wsa_state available to the rest of the code is formally
* wrong. But the structures we use are [beleived to be] invariable
* among Winsock DLLs, while API availability is [expected to be]
* probed at run-time with DSO_global_lookup.
*/
if (WSAStartup(0x0202, &wsa_state) != 0) {
err = WSAGetLastError();
WOLFSSL_ERROR(BIO_WSASTARTUP_E);
return -1;
}
}
# endif /* USE_WINDOWS_API */
return 1;
}
void WOLFCRYPT_BIO_sock_cleanup(void)
{
#ifdef USE_WINDOWS_API
if (wsa_init_done) {
wsa_init_done = 0;
WSACleanup();
}
#endif
}
int WOLFCRYPT_BIO_get_accept_socket(char *host, int bind_mode)
{
int ret = 0;
union {
struct sockaddr sa;
struct sockaddr_in sa_in;
#ifdef TEST_IPV6
struct sockaddr_in6 sa_in6;
#endif
} server, client;
int s = WOLFSSL_SOCKET_INVALID, cs, addrlen;
unsigned char ip[4];
unsigned short port;
char *str = NULL;
char *h, *p, *e;
unsigned long l;
int err_num;
if (WOLFCRYPT_BIO_sock_init() != 1)
return WOLFSSL_SOCKET_INVALID;
str = strdup(host);
if (str == NULL)
return WOLFSSL_SOCKET_INVALID;
h = p = NULL;
h = str;
for (e = str; *e; e++) {
if (*e == ':') {
p = e;
} else if (*e == '/') {
*e = '\0';
break;
}
}
if (p)
*p++ = '\0'; /* points at last ':', '::port' is special
* [see below] */
else
p = h, h = NULL;
if (!WOLFCRYPT_BIO_get_port(p, &port))
goto err;
memset((char *)&server, 0, sizeof(server));
server.sa_in.sin_family = AF_INET;
server.sa_in.sin_port = htons(port);
addrlen = sizeof(server.sa_in);
if (h == NULL || strcmp(h, "*") == 0)
server.sa_in.sin_addr.s_addr = INADDR_ANY;
else {
if (!WOLFCRYPT_BIO_get_host_ip(h, &(ip[0])))
goto err;
l = (unsigned long)
((unsigned long)ip[0] << 24L) |
((unsigned long)ip[1] << 16L) |
((unsigned long)ip[2] << 8L) |
((unsigned long)ip[3]);
server.sa_in.sin_addr.s_addr = htonl(l);
}
again:
s = socket(server.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if (s == WOLFSSL_SOCKET_INVALID) {
WOLFSSL_ERROR(BIO_CREATE_SOCKET_E);
goto err;
}
#ifdef SO_REUSEADDR
if (bind_mode == BIO_BIND_REUSEADDR) {
int i = 1;
ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&i, sizeof(i));
bind_mode = BIO_BIND_NORMAL;
}
#endif /* SO_REUSEADDR */
if (bind(s, &server.sa, addrlen) == -1) {
#ifdef SO_REUSEADDR
#ifdef USE_WINDOWS_API
err_num = WSAGetLastError();
if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
(err_num == WSAEADDRINUSE))
#else
err_num = errno;
if ((bind_mode == BIO_BIND_REUSEADDR_IF_UNUSED) &&
(err_num == EADDRINUSE))
#endif /* USE_WINDOWS_API */
{
client = server;
if (h == NULL || strcmp(h, "*") == 0) {
#ifdef TEST_IPV6
if (client.sa.sa_family == AF_INET6) {
XMEMSET(&client.sa_in6.sin6_addr, 0,
sizeof(client.sa_in6.sin6_addr));
client.sa_in6.sin6_addr.s6_addr[15] = 1;
}
else
#endif
if (client.sa.sa_family == AF_INET) {
client.sa_in.sin_addr.s_addr = htonl(0x7F000001);
}
else
goto err;
}
cs = socket(client.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if (cs != WOLFSSL_SOCKET_INVALID) {
int ii;
ii = connect(cs, &client.sa, addrlen);
#ifdef USE_WINDOWS_API
closesocket(cs);
#else
close(cs);
#endif
if (ii == WOLFSSL_SOCKET_INVALID) {
bind_mode = BIO_BIND_REUSEADDR;
#ifdef USE_WINDOWS_API
closesocket(s);
#else
close(s);
#endif
goto again;
}
}
}
#endif /* SO_REUSEADDR */
WOLFSSL_ERROR(BIO_BIND_SOCKET_E);
goto err;
}
if (listen(s, MAX_LISTEN) == -1) {
WOLFSSL_ERROR(BIO_LISTEN_SOCKET_E);
goto err;
}
ret = 1;
err:
if (str != NULL)
free(str);
if (!ret && (s != WOLFSSL_SOCKET_INVALID)) {
#ifdef USE_WINDOWS_API
closesocket(s);
#else
close(s);
#endif
s = WOLFSSL_SOCKET_INVALID;
}
return s;
}
int WOLFCRYPT_BIO_accept(int sock, char **addr)
{
int dsock = WOLFSSL_SOCKET_INVALID;
unsigned long l;
struct {
union {
size_t s;
int i;
} len;
union {
struct sockaddr sa;
struct sockaddr_in sa_in;
#ifdef TEST_IPV6
struct sockaddr_in sa_in6;
#endif
} from;
} sa;
sa.len.s = 0;
sa.len.i = sizeof(sa.from);
memset(&sa.from, 0, sizeof(sa.from));
dsock = accept(sock, &sa.from.sa, (void *)&sa.len);
if (sizeof(sa.len.i) != sizeof(sa.len.s) && !sa.len.i) {
if (sa.len.s > sizeof(sa.from)) {
WOLFSSL_ERROR(MEMORY_E);
goto end;
}
sa.len.i = (int)sa.len.s;
}
if (dsock == WOLFSSL_SOCKET_INVALID) {
if (WOLFCRYPT_BIO_sock_should_retry(dsock))
return -2;
WOLFSSL_ERROR(BIO_ACCEPT_E);
goto end;
}
if (addr == NULL || sa.from.sa.sa_family != AF_INET)
goto end;
if (*addr == NULL) {
*addr = XMALLOC(24, 0, DYNAMIC_TYPE_OPENSSL);
if (*addr == NULL) {
WOLFSSL_ERROR(MEMORY_E);
goto end;
}
}
l = ntohl(sa.from.sa_in.sin_addr.s_addr);
XSNPRINTF(*addr, 24, "%d.%d.%d.%d:%d",
(unsigned char)(l >> 24L) & 0xff,
(unsigned char)(l >> 16L) & 0xff,
(unsigned char)(l >> 8L) & 0xff,
(unsigned char)(l) & 0xff, ntohs(sa.from.sa_in.sin_port));
end:
return dsock;
}
int WOLFCRYPT_BIO_set_tcp_nsigpipe(int s, int on)
{
int ret = 0;
#ifndef USE_WINDOWS_API
#ifdef SO_NOSIGPIPE
ret = setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &on, sizeof(on));
#else /* no S_NOSIGPIPE */
(void) s;
(void) on;
signal(SIGPIPE, SIG_IGN);
#endif /* S_NOSIGPIPE */
#endif /* USE_WINDOWS_API */
return (ret == 0);
}
int WOLFCRYPT_BIO_set_tcp_ndelay(int s, int on)
{
int ret = 0;
#if defined(TCP_NODELAY)
#ifdef SOL_TCP
int opt = SOL_TCP;
#else
int opt = IPPROTO_TCP;
#endif
ret = setsockopt(s, opt, TCP_NODELAY, (char *)&on, sizeof(on));
#else
(void) s;
(void) on;
#endif /* TCP_NODELAY */
return (ret == 0);
}
int WOLFCRYPT_BIO_socket_nbio(int s, int mode)
{
#ifdef USE_WINDOWS_API
unsigned long blocking = mode;
int ret = ioctlsocket(s, FIONBIO, &blocking);
return (ret == 0);
#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \
|| defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS)
/* non blocking not supported, for now */
return -1;
#else
int flags = fcntl(s, F_GETFL, 0);
if (flags)
flags = fcntl(s, F_SETFL, flags | mode);
return (flags == 0);
#endif
}
#endif /* OPENSSL_EXTRA */

725
wolfcrypt/src/bio_f_ssl.c Normal file
View File

@@ -0,0 +1,725 @@
/* bio_f_ssl.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/socket.h>
#include <errno.h>
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/ssl.h>
#include <wolfssl/internal.h>
#include <wolfssl/openssl/bio.h>
typedef struct {
WOLFSSL *ssl;
/* re-negotiate every time the total number of bytes is this size */
int num_renegotiates;
unsigned long renegotiate_count;
unsigned long byte_count;
unsigned long renegotiate_timeout;
unsigned long last_time;
} WOLFCRYPT_BIO_SSL;
static int WOLFCRYPT_BIO_ssl_write(WOLFCRYPT_BIO *bio,
const char *data, int size);
static int WOLFCRYPT_BIO_ssl_read(WOLFCRYPT_BIO *bio, char *data, int size);
static int WOLFCRYPT_BIO_ssl_puts(WOLFCRYPT_BIO *bio, const char *str);
static long WOLFCRYPT_BIO_ssl_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_ssl_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_ssl_free(WOLFCRYPT_BIO *bio);
static long WOLFCRYPT_BIO_ssl_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_ssl_method = {
BIO_TYPE_SSL,
"SSL",
WOLFCRYPT_BIO_ssl_write,
WOLFCRYPT_BIO_ssl_read,
WOLFCRYPT_BIO_ssl_puts,
NULL, /* gets */
WOLFCRYPT_BIO_ssl_ctrl,
WOLFCRYPT_BIO_ssl_new,
WOLFCRYPT_BIO_ssl_free,
WOLFCRYPT_BIO_ssl_callback_ctrl,
};
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_ssl(void)
{
return (&WOLFCRYPT_BIO_ssl_method);
}
static int WOLFCRYPT_BIO_ssl_new(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bio->ptr = (WOLFCRYPT_BIO_SSL *)XMALLOC(sizeof(WOLFCRYPT_BIO_SSL),
0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return 0;
}
XMEMSET(bio->ptr, 0, sizeof(WOLFCRYPT_BIO_SSL));
bio->init = 0;
bio->flags = 0;
return 1;
}
static int WOLFCRYPT_BIO_ssl_free(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_ssl_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (bio->ptr != NULL) {
WOLFCRYPT_BIO_SSL *bssl = (WOLFCRYPT_BIO_SSL *)bio->ptr;
if (bssl->ssl != NULL) {
wolfSSL_shutdown(bssl->ssl);
if (bio->shutdown && bio->init) {
WOLFSSL_MSG("Free BIO ssl");
wolfSSL_free(bssl->ssl);
}
}
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
bio->ptr = NULL;
}
if (bio->shutdown) {
bio->init = 0;
bio->flags = 0;
}
return 1;
}
static int WOLFCRYPT_BIO_ssl_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = 1;
WOLFCRYPT_BIO_SSL *bssl;
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
if (data == NULL)
return 0;
bssl = (WOLFCRYPT_BIO_SSL *)bio->ptr;
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = wolfSSL_read(bssl->ssl, data, size);
switch (wolfSSL_get_error(bssl->ssl, ret)) {
case SSL_ERROR_NONE:
if (ret <= 0)
break;
#ifdef HAVE_SECURE_RENEGOTIATION
{
int r = 0;
if (bssl->renegotiate_count > 0) {
bssl->byte_count += ret;
if (bssl->byte_count > bssl->renegotiate_count) {
bssl->byte_count = 0;
bssl->num_renegotiates++;
wolfSSL_Rehandshake(bssl->ssl);
r = 1;
}
}
if ((bssl->renegotiate_timeout > 0) && !r) {
unsigned long tm;
tm = (unsigned long)time(NULL);
if (tm > bssl->last_time + bssl->renegotiate_timeout) {
bssl->last_time = tm;
bssl->num_renegotiates++;
wolfSSL_Rehandshake(bssl->ssl);
}
}
}
#endif
break;
case SSL_ERROR_WANT_READ:
WOLFCRYPT_BIO_set_retry_read(bio);
break;
case SSL_ERROR_WANT_WRITE:
WOLFCRYPT_BIO_set_retry_write(bio);
break;
case SSL_ERROR_WANT_X509_LOOKUP:
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
break;
case SSL_ERROR_WANT_ACCEPT:
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_ACCEPT;
break;
case SSL_ERROR_WANT_CONNECT:
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_CONNECT;
break;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
case SSL_ERROR_ZERO_RETURN:
break;
default:
break;
}
return ret;
}
static int WOLFCRYPT_BIO_ssl_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret;
WOLFCRYPT_BIO_SSL *bssl;
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
if (data == NULL)
return 0;
bssl = (WOLFCRYPT_BIO_SSL *)bio->ptr;
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = wolfSSL_write(bssl->ssl, data, size);
switch (wolfSSL_get_error(bssl->ssl, ret)) {
case SSL_ERROR_NONE:
if (ret <= 0)
break;
#ifdef HAVE_SECURE_RENEGOTIATION
{
int r = 0;
if (bssl->renegotiate_count > 0) {
bssl->byte_count += ret;
if (bssl->byte_count > bssl->renegotiate_count) {
bssl->byte_count = 0;
bssl->num_renegotiates++;
wolfSSL_Rehandshake(bssl->ssl);
r = 1;
}
}
if ((bssl->renegotiate_timeout > 0) && !r) {
unsigned long tm;
tm = (unsigned long)time(NULL);
if (tm > bssl->last_time + bssl->renegotiate_timeout) {
bssl->last_time = tm;
bssl->num_renegotiates++;
wolfSSL_Rehandshake(bssl->ssl);
}
}
}
#endif
break;
case SSL_ERROR_WANT_WRITE:
WOLFCRYPT_BIO_set_retry_write(bio);
break;
case SSL_ERROR_WANT_READ:
WOLFCRYPT_BIO_set_retry_read(bio);
break;
case SSL_ERROR_WANT_X509_LOOKUP:
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
break;
case SSL_ERROR_WANT_CONNECT:
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_CONNECT;
break;
case SSL_ERROR_SYSCALL:
case SSL_ERROR_SSL:
break;
default:
break;
}
return ret;
}
static int WOLFCRYPT_BIO_ssl_set_bio(WOLFSSL *ssl, WOLFCRYPT_BIO *rbio,
WOLFCRYPT_BIO *wbio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_ssl_set_bio");
if (ssl == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
if (ssl->biord != NULL && ssl->biord != rbio)
WOLFCRYPT_BIO_free_all(ssl->biord);
if (ssl->biowr != NULL && ssl->biowr != wbio && ssl->biord != ssl->biowr)
WOLFCRYPT_BIO_free_all(ssl->biowr);
ssl->biord = rbio;
wolfSSL_set_rfd(ssl, rbio->num);
ssl->biowr = wbio;
wolfSSL_set_wfd(ssl, wbio->num);
return 1;
}
static long WOLFCRYPT_BIO_ssl_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr)
{
WOLFCRYPT_BIO_SSL *bssl;
long ret = 1;
WOLFSSL_ENTER("WOLFCRYPT_BIO_ssl_ctrl");
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bssl = (WOLFCRYPT_BIO_SSL *)bio->ptr;
if ((bssl->ssl == NULL) && (cmd != BIO_C_SET_SSL)) {
WOLFSSL_MSG("Set SSL not possible, ssl pointer NULL\n");
return 0;
}
switch (cmd) {
case BIO_CTRL_RESET:
wolfSSL_shutdown(bssl->ssl);
ret = (long)wolfSSL_negotiate(bssl->ssl);
if (ret <= 0)
break;
wolfSSL_clear(bssl->ssl);
if (bio->next_bio != NULL)
ret = WOLFCRYPT_BIO_ctrl(bio->next_bio, cmd, num, ptr);
else if (bssl->ssl->biord != NULL)
ret = WOLFCRYPT_BIO_ctrl(bssl->ssl->biord, cmd, num, ptr);
else
ret = 1;
break;
case BIO_CTRL_INFO:
ret = 0;
break;
case BIO_C_SSL_MODE:
if (num) /* client mode */
wolfSSL_set_connect_state(bssl->ssl);
else
wolfSSL_set_accept_state(bssl->ssl);
break;
case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT:
ret = bssl->renegotiate_timeout;
if (num < 60)
num = 5;
bssl->renegotiate_timeout = (unsigned long)num;
bssl->last_time = (unsigned long)time(NULL);
break;
case BIO_C_SET_SSL_RENEGOTIATE_BYTES:
ret = bssl->renegotiate_count;
if (num >= 512)
bssl->renegotiate_count = (unsigned long)num;
break;
case BIO_C_GET_SSL_NUM_RENEGOTIATES:
ret = bssl->num_renegotiates;
break;
case BIO_C_SET_SSL:
if (bssl->ssl != NULL) {
WOLFCRYPT_BIO_ssl_free(bio);
if (!WOLFCRYPT_BIO_ssl_new(bio))
return 0;
}
bio->shutdown = (int)num;
bssl->ssl = (WOLFSSL *)ptr;
if (bssl->ssl->biord != NULL) {
if (bio->next_bio != NULL)
WOLFCRYPT_BIO_push(bssl->ssl->biord, bio->next_bio);
bio->next_bio = bssl->ssl->biord;
if (LockMutex(&bssl->ssl->biord->refMutex) != 0) {
WOLFSSL_MSG("Couldn't lock count mutex");
ret = 0;
break;
}
bssl->ssl->biord->references++;
UnLockMutex(&bssl->ssl->biord->refMutex);
}
bio->init = 1;
break;
case BIO_C_GET_SSL:
if (ptr != NULL)
*(WOLFSSL **)ptr = bssl->ssl;
else
ret = 0;
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_WPENDING:
ret = WOLFCRYPT_BIO_ctrl(bssl->ssl->biowr, cmd, num, ptr);
break;
case BIO_CTRL_PENDING:
ret = wolfSSL_pending(bssl->ssl);
if (!ret)
ret = WOLFCRYPT_BIO_pending(bssl->ssl->biord);
break;
case BIO_CTRL_FLUSH:
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = WOLFCRYPT_BIO_ctrl(bssl->ssl->biowr, cmd, num, ptr);
WOLFCRYPT_BIO_copy_next_retry(bio);
break;
case BIO_CTRL_PUSH:
if (bio->next_bio != NULL && bio->next_bio != bssl->ssl->biord) {
ret = WOLFCRYPT_BIO_ssl_set_bio(bssl->ssl,
bio->next_bio, bio->next_bio);
if (LockMutex(&bio->next_bio->refMutex) != 0) {
WOLFSSL_MSG("Couldn't lock count mutex");
ret = 0;
break;
}
bio->next_bio->references++;
UnLockMutex(&bio->next_bio->refMutex);
}
break;
case BIO_CTRL_POP:
if (bio == ptr) {
if (bssl->ssl->biord != bssl->ssl->biowr)
WOLFCRYPT_BIO_free_all(bssl->ssl->biowr);
if (bio->next_bio != NULL) {
if (LockMutex(&bio->next_bio->refMutex) != 0) {
WOLFSSL_MSG("Couldn't lock count mutex");
ret = 0;
break;
}
bio->next_bio->references--;
UnLockMutex(&bio->next_bio->refMutex);
}
bssl->ssl->biowr = NULL;
bssl->ssl->biord = NULL;
}
break;
case BIO_C_DO_STATE_MACHINE:
WOLFCRYPT_BIO_clear_retry_flags(bio);
bio->retry_reason = 0;
ret = (long)wolfSSL_negotiate(bssl->ssl);
switch (wolfSSL_get_error(bssl->ssl, (int)ret)) {
case SSL_ERROR_WANT_READ:
WOLFCRYPT_BIO_set_flags(bio, BIO_FLAGS_READ |
BIO_FLAGS_SHOULD_RETRY);
break;
case SSL_ERROR_WANT_WRITE:
WOLFCRYPT_BIO_set_flags(bio, BIO_FLAGS_WRITE |
BIO_FLAGS_SHOULD_RETRY);
break;
case SSL_ERROR_WANT_CONNECT:
WOLFCRYPT_BIO_set_flags(bio, BIO_FLAGS_IO_SPECIAL |
BIO_FLAGS_SHOULD_RETRY);
bio->retry_reason = bio->next_bio->retry_reason;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_SSL_X509_LOOKUP;
break;
default:
break;
}
break;
case BIO_CTRL_DUP:
{
WOLFCRYPT_BIO *dbio;
dbio = (WOLFCRYPT_BIO *)ptr;
if (((WOLFCRYPT_BIO_SSL *)dbio->ptr)->ssl != NULL)
wolfSSL_free(((WOLFCRYPT_BIO_SSL *)dbio->ptr)->ssl);
/* add copy ssl */
((WOLFCRYPT_BIO_SSL *)dbio->ptr)->ssl = wolfSSL_dup(bssl->ssl);
((WOLFCRYPT_BIO_SSL *)dbio->ptr)->renegotiate_count =
bssl->renegotiate_count;
((WOLFCRYPT_BIO_SSL *)dbio->ptr)->byte_count = bssl->byte_count;
((WOLFCRYPT_BIO_SSL *)dbio->ptr)->renegotiate_timeout =
bssl->renegotiate_timeout;
((WOLFCRYPT_BIO_SSL *)dbio->ptr)->last_time = bssl->last_time;
if (((WOLFCRYPT_BIO_SSL *)dbio->ptr)->ssl == NULL)
ret = 0;
}
break;
case BIO_C_GET_FD:
ret = WOLFCRYPT_BIO_ctrl(bssl->ssl->biord, cmd, num, ptr);
break;
case BIO_CTRL_SET_CALLBACK:
/* not supported */
WOLFSSL_MSG("BIO_CTRL_SET_CALLBACK not supported\n");
ret = 0;
break;
case BIO_CTRL_GET_CALLBACK:
/* not supported */
WOLFSSL_MSG("BIO_CTRL_GET_CALLBACK not supported\n");
ptr = NULL;
ret = 0;
break;
default:
ret = WOLFCRYPT_BIO_ctrl(bssl->ssl->biord, cmd, num, ptr);
break;
}
return ret;
}
static long WOLFCRYPT_BIO_ssl_callback_ctrl(WOLFCRYPT_BIO *bio,
int cmd, WOLFCRYPT_BIO_info_cb *fp)
{
long ret = 1;
WOLFCRYPT_BIO_SSL *bssl;
WOLFSSL_ENTER("WOLFCRYPT_BIO_ssl_callback_ctrl");
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bssl = (WOLFCRYPT_BIO_SSL *)bio->ptr;
switch (cmd) {
case BIO_CTRL_SET_CALLBACK:
/* not supported */
WOLFSSL_MSG("BIO_CTRL_GET_CALLBACK not supported\n");
ret = 0;
break;
default:
ret = WOLFCRYPT_BIO_callback_ctrl(bssl->ssl->biord, cmd, fp);
break;
}
return ret;
}
static int WOLFCRYPT_BIO_ssl_puts(WOLFCRYPT_BIO *bio, const char *str)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_ssl_puts");
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
return WOLFCRYPT_BIO_ssl_write(bio, str, (int)strlen(str));
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_buffer_ssl_connect(WOLFSSL_CTX *ctx)
{
WOLFCRYPT_BIO *bio = NULL, *buf = NULL, *ssl = NULL;
WOLFSSL_ENTER("WOLFCRYPT_BIO_new_buffer_ssl_connect");
if (ctx == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
buf = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_buffer());
if (buf == NULL)
return NULL;
ssl = WOLFCRYPT_BIO_new_ssl_connect(ctx);
if (ssl == NULL)
goto err;
bio = WOLFCRYPT_BIO_push(buf, ssl);
if (bio == NULL)
goto err;
return bio;
err:
if (buf != NULL)
WOLFCRYPT_BIO_free(buf);
if (ssl != NULL)
WOLFCRYPT_BIO_free(ssl);
return NULL;
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_ssl_connect(WOLFSSL_CTX *ctx)
{
WOLFCRYPT_BIO *bio = NULL, *con = NULL, *ssl = NULL;
WOLFSSL_ENTER("WOLFCRYPT_BIO_new_ssl_connect");
if (ctx == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
con = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_connect());
if (con == NULL)
return NULL;
ssl = WOLFCRYPT_BIO_new_ssl(ctx, 1);
if (ssl == NULL)
goto err;
bio = WOLFCRYPT_BIO_push(ssl, con);
if (bio == NULL)
goto err;
return bio;
err:
if (con != NULL)
WOLFCRYPT_BIO_free(con);
if (ssl != NULL)
WOLFCRYPT_BIO_free(ssl);
return NULL;
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_ssl(WOLFSSL_CTX *ctx, int mode)
{
WOLFCRYPT_BIO *bio;
WOLFSSL *ssl;
WOLFSSL_ENTER("WOLFCRYPT_BIO_new_ssl");
if (ctx == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_ssl());
if (bio == NULL)
return NULL;
ssl = wolfSSL_new(ctx);
if (ssl == NULL) {
WOLFCRYPT_BIO_free(bio);
return NULL;
}
if (mode) /* client */
wolfSSL_set_connect_state(ssl);
else
wolfSSL_set_accept_state(ssl);
WOLFCRYPT_BIO_set_ssl(bio, ssl, BIO_CLOSE);
return bio;
}
void WOLFCRYPT_BIO_ssl_shutdown(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_ssl_shutdown");
while (bio != NULL) {
if (bio->method->type == BIO_TYPE_SSL) {
wolfSSL_shutdown(((WOLFCRYPT_BIO_SSL *)bio->ptr)->ssl);
break;
}
bio = bio->next_bio;
}
}
#endif /* OPENSSL_EXTRA */

View File

@@ -0,0 +1,554 @@
/* bio_m_accept.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#ifdef USE_WINDOWS_API
#include <winsock2.h>
#include <process.h>
#endif /* USE_WINDOWS_API */
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
/* Socket Handling */
#ifndef WOLFSSL_SOCKET_INVALID
#ifdef USE_WINDOWS_API
#define WOLFSSL_SOCKET_INVALID ((SOCKET)WOLFSSL_SOCKET_INVALID)
#else
#define WOLFSSL_SOCKET_INVALID (0)
#endif
#endif /* WOLFSSL_SOCKET_INVALID */
typedef struct {
int state;
int nbio;
char *param_addr;
char *ip_port;
int accept_sock;
int accept_nbio;
/*
* If 0, it means normal, if 1, do a connect on bind failure, and if
* there is no-one listening, bind with SO_REUSEADDR. If 2, always use
* SO_REUSEADDR.
*/
int bind_mode;
/* used to force some socket options like NO_SIGPIPE, TCP_NODELAY */
int options;
WOLFCRYPT_BIO *bio_chain;
} WOLFCRYPT_BIO_ACCEPT;
static int WOLFCRYPT_BIO_accept_write(WOLFCRYPT_BIO *bio,
const char *data, int size);
static int WOLFCRYPT_BIO_accept_read(WOLFCRYPT_BIO *bio, char *data, int size);
static int WOLFCRYPT_BIO_accept_puts(WOLFCRYPT_BIO *bio, const char *str);
static long WOLFCRYPT_BIO_accept_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr);
static int WOLFCRYPT_BIO_accept_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_accept_free(WOLFCRYPT_BIO *bio);
static void WOLFCRYPT_BIO_accept_close_socket(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_accept_state(WOLFCRYPT_BIO *bio,
WOLFCRYPT_BIO_ACCEPT *c);
# define ACPT_S_BEFORE 1
# define ACPT_S_GET_ACCEPT_SOCKET 2
# define ACPT_S_OK 3
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_accept_method = {
BIO_TYPE_ACCEPT,
"Socket accept",
WOLFCRYPT_BIO_accept_write,
WOLFCRYPT_BIO_accept_read,
WOLFCRYPT_BIO_accept_puts,
NULL, /* gets */
WOLFCRYPT_BIO_accept_ctrl,
WOLFCRYPT_BIO_accept_new,
WOLFCRYPT_BIO_accept_free,
NULL,
};
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_accept(void)
{
return (&WOLFCRYPT_BIO_accept_method);
}
static int WOLFCRYPT_BIO_accept_new(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_accept_new");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
bio->init = 0;
bio->num = WOLFSSL_SOCKET_INVALID;
bio->flags = 0;
bio->ptr = (WOLFCRYPT_BIO_ACCEPT *)
XMALLOC(sizeof(WOLFCRYPT_BIO_ACCEPT), 0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL)
return 0;
XMEMSET(bio->ptr, 0, sizeof(WOLFCRYPT_BIO_ACCEPT));
((WOLFCRYPT_BIO_ACCEPT *)bio->ptr)->accept_sock = WOLFSSL_SOCKET_INVALID;
((WOLFCRYPT_BIO_ACCEPT *)bio->ptr)->bind_mode = BIO_BIND_NORMAL;
((WOLFCRYPT_BIO_ACCEPT *)bio->ptr)->options = 0;
((WOLFCRYPT_BIO_ACCEPT *)bio->ptr)->state = ACPT_S_BEFORE;
bio->shutdown = 1;
return 1;
}
static void WOLFCRYPT_BIO_accept_close_socket(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_ACCEPT *accept;
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return;
}
accept = (WOLFCRYPT_BIO_ACCEPT *)bio->ptr;
if (accept->accept_sock != WOLFSSL_SOCKET_INVALID) {
shutdown(accept->accept_sock, SHUT_RDWR);
#ifdef USE_WINDOWS_API
closesocket(accept->accept_sock);
#else
close(accept->accept_sock);
#endif
accept->accept_sock = WOLFSSL_SOCKET_INVALID;
bio->num = WOLFSSL_SOCKET_INVALID;
}
}
static int WOLFCRYPT_BIO_accept_free(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_accept_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (!bio->shutdown)
return 1;
WOLFCRYPT_BIO_accept_close_socket(bio);
if (bio->ptr != NULL) {
WOLFCRYPT_BIO_ACCEPT *accept = (WOLFCRYPT_BIO_ACCEPT *)bio->ptr;
if (accept->param_addr != NULL)
XFREE(accept->param_addr, 0, DYNAMIC_TYPE_OPENSSL);
if (accept->ip_port != NULL)
XFREE(accept->ip_port, 0, DYNAMIC_TYPE_OPENSSL);
if (accept->bio_chain != NULL)
WOLFCRYPT_BIO_free(accept->bio_chain);
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
bio->ptr = NULL;
}
bio->flags = 0;
bio->init = 0;
return 1;
}
static int WOLFCRYPT_BIO_accept_state(WOLFCRYPT_BIO *bio,
WOLFCRYPT_BIO_ACCEPT *accept)
{
WOLFCRYPT_BIO *nbio = NULL;
int s = -1;
int dsock;
if (bio == NULL || accept == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
again:
switch (accept->state) {
case ACPT_S_BEFORE:
if (accept->param_addr == NULL) {
WOLFSSL_ERROR(BIO_NO_PORT_E);
return -1;
}
s = WOLFCRYPT_BIO_get_accept_socket(accept->param_addr,
accept->bind_mode);
if (s == WOLFSSL_SOCKET_INVALID)
return -1;
if (accept->accept_nbio) {
if (!WOLFCRYPT_BIO_socket_nbio(s, 1)) {
#ifdef USE_WINDOWS_API
closesocket(s);
#else
close(s);
#endif
WOLFSSL_ERROR(BIO_NBIO_E);
return -1;
}
}
/* TCP NO DELAY */
if (accept->options & 1) {
if (!WOLFCRYPT_BIO_set_tcp_ndelay(s, 1)) {
#ifdef USE_WINDOWS_API
closesocket(s);
#else
close(s);
#endif
WOLFSSL_ERROR(BIO_OPTIONS_E);
return -1;
}
}
/* IGNORE SIGPIPE */
if (accept->options & 2) {
if (!WOLFCRYPT_BIO_set_tcp_nsigpipe(s, 1)) {
#ifdef USE_WINDOWS_API
closesocket(s);
#else
close(s);
#endif
WOLFSSL_ERROR(BIO_OPTIONS_E);
return -1;
}
}
accept->accept_sock = s;
bio->num = s;
accept->state = ACPT_S_GET_ACCEPT_SOCKET;
return 1;
break;
case ACPT_S_GET_ACCEPT_SOCKET:
if (bio->next_bio != NULL) {
accept->state = ACPT_S_OK;
goto again;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
bio->retry_reason = 0;
dsock = WOLFCRYPT_BIO_accept(accept->accept_sock, &accept->ip_port);
/* retry case */
if (dsock == -2) {
WOLFCRYPT_BIO_set_retry_special(bio);
bio->retry_reason = BIO_RR_ACCEPT;
return -1;
}
if (dsock < 0)
return dsock;
nbio = WOLFCRYPT_BIO_new_socket(dsock, BIO_CLOSE);
if (nbio == NULL)
goto err;
WOLFCRYPT_BIO_set_callback(nbio,
WOLFCRYPT_BIO_get_callback(bio));
WOLFCRYPT_BIO_set_callback_arg(nbio,
WOLFCRYPT_BIO_get_callback_arg(bio));
if (accept->nbio) {
if (!WOLFCRYPT_BIO_socket_nbio(dsock, 1)) {
WOLFSSL_ERROR(BIO_NBIO_E);
goto err;
}
}
/*
* If the accept BIO has an bio_chain, we dup it and put the new
* socket at the end.
*/
if (accept->bio_chain != NULL) {
WOLFCRYPT_BIO *dbio = WOLFCRYPT_BIO_dup_chain(accept->bio_chain);
if (dbio == NULL)
goto err;
if (!WOLFCRYPT_BIO_push(dbio, nbio))
goto err;
nbio = dbio;
}
if (WOLFCRYPT_BIO_push(bio, nbio) == NULL)
goto err;
accept->state = ACPT_S_OK;
return 1;
err:
if (nbio != NULL)
WOLFCRYPT_BIO_free(nbio);
else if (s >= 0)
#ifdef USE_WINDOWS_API
closesocket(s);
#else
close(s);
#endif
break;
case ACPT_S_OK:
if (bio->next_bio == NULL) {
accept->state = ACPT_S_GET_ACCEPT_SOCKET;
goto again;
}
return 1;
break;
default:
break;
}
return 0;
}
static int WOLFCRYPT_BIO_accept_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = 0;
WOLFCRYPT_BIO_ACCEPT *accept;
if (bio == NULL || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
accept = (WOLFCRYPT_BIO_ACCEPT *)bio->ptr;
while (bio->next_bio == NULL) {
ret = WOLFCRYPT_BIO_accept_state(bio, accept);
if (ret <= 0)
return ret;
}
ret = WOLFCRYPT_BIO_read(bio->next_bio, data, size);
WOLFCRYPT_BIO_copy_next_retry(bio);
return ret;
}
static int WOLFCRYPT_BIO_accept_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret = 0;
WOLFCRYPT_BIO_ACCEPT *accept;
if (bio == NULL || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
accept = (WOLFCRYPT_BIO_ACCEPT *)bio->ptr;
while (bio->next_bio == NULL) {
ret = WOLFCRYPT_BIO_accept_state(bio, accept);
if (ret <= 0)
return ret;
}
ret = WOLFCRYPT_BIO_write(bio->next_bio, data, size);
WOLFCRYPT_BIO_copy_next_retry(bio);
return ret;
}
static long WOLFCRYPT_BIO_accept_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
int *ip;
long ret = 1;
WOLFCRYPT_BIO_ACCEPT *accept;
char **pp;
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
accept = (WOLFCRYPT_BIO_ACCEPT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ret = 0;
accept->state = ACPT_S_BEFORE;
WOLFCRYPT_BIO_accept_close_socket(bio);
bio->flags = 0;
break;
case BIO_C_DO_STATE_MACHINE:
/* use this one to start the connection */
ret = (long)WOLFCRYPT_BIO_accept_state(bio, accept);
break;
case BIO_C_SET_ACCEPT:
if (ptr != NULL) {
if (num == 0) {
bio->init = 1;
if (accept->param_addr != NULL)
XFREE(accept->param_addr, 0, DYNAMIC_TYPE_OPENSSL);
accept->param_addr = strdup(ptr);
}
else if (num == 1) {
accept->accept_nbio = (ptr != NULL);
}
else if (num == 2) {
if (accept->bio_chain != NULL)
WOLFCRYPT_BIO_free(accept->bio_chain);
accept->bio_chain = (WOLFCRYPT_BIO *)ptr;
}
}
break;
case BIO_C_SET_NBIO:
accept->nbio = (int)num;
break;
case BIO_C_SET_FD:
bio->init = 1;
bio->num = *((int *)ptr);
accept->accept_sock = bio->num;
accept->state = ACPT_S_GET_ACCEPT_SOCKET;
bio->shutdown = (int)num;
bio->init = 1;
break;
case BIO_C_GET_FD:
if (bio->init) {
ip = (int *)ptr;
if (ip != NULL)
*ip = accept->accept_sock;
ret = accept->accept_sock;
}
else
ret = -1;
break;
case BIO_C_GET_ACCEPT:
if (bio->init) {
if (ptr != NULL) {
pp = (char **)ptr;
*pp = accept->param_addr;
}
else
ret = -1;
}
else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
case BIO_CTRL_DUP:
break;
case BIO_C_SET_BIND_MODE:
accept->bind_mode = (int)num;
break;
case BIO_C_GET_BIND_MODE:
ret = (long)accept->bind_mode;
break;
case BIO_C_SET_EX_ARG:
accept->options = (int)num;
break;
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_accept_puts(WOLFCRYPT_BIO *bio, const char *str)
{
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
return WOLFCRYPT_BIO_accept_write(bio, str, (int)strlen(str));
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_accept(const char *str)
{
WOLFCRYPT_BIO *bio;
if (str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_accept());
if (bio == NULL)
return NULL;
if (WOLFCRYPT_BIO_set_accept_port(bio, str))
return bio;
WOLFCRYPT_BIO_free(bio);
return NULL;
}
#endif /* OPENSSL_EXTRA */

715
wolfcrypt/src/bio_m_conn.c Normal file
View File

@@ -0,0 +1,715 @@
/* bio_m_conn.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#ifdef USE_WINDOWS_API
#include <winsock2.h>
#include <process.h>
#endif /* USE_WINDOWS_API */
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
/* Socket Handling */
#ifndef WOLFSSL_SOCKET_INVALID
#ifdef USE_WINDOWS_API
#define WOLFSSL_SOCKET_INVALID ((SOCKET)INVALID_SOCKET)
#else
#define WOLFSSL_SOCKET_INVALID (0)
#endif
#endif /* WOLFSSL_SOCKET_INVALID */
static int WOLFCRYPT_BIO_conn_write(WOLFCRYPT_BIO *bio,
const char *data, int size);
static int WOLFCRYPT_BIO_conn_read(WOLFCRYPT_BIO *bio, char *data, int size);
static int WOLFCRYPT_BIO_conn_puts(WOLFCRYPT_BIO *bio, const char *str);
static long WOLFCRYPT_BIO_conn_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_conn_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_conn_free(WOLFCRYPT_BIO *bio);
static long WOLFCRYPT_BIO_conn_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
WOLFCRYPT_BIO_info_cb *fp);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_conn_method = {
BIO_TYPE_SOCKET,
"Socket connect",
WOLFCRYPT_BIO_conn_write,
WOLFCRYPT_BIO_conn_read,
WOLFCRYPT_BIO_conn_puts,
NULL, /* gets */
WOLFCRYPT_BIO_conn_ctrl,
WOLFCRYPT_BIO_conn_new,
WOLFCRYPT_BIO_conn_free,
WOLFCRYPT_BIO_conn_callback_ctrl,
};
typedef struct {
int state;
int nbio;
/* keep received Hostname and Port */
char *pHostname;
char *pPort;
/* internal usage */
unsigned char ip[4];
unsigned short port;
struct sockaddr_in them;
/*
* called when the connection is initially made callback(BIO,state,ret);
* The callback should return 'ret'. state is for compatibility with the
* ssl info_callback
*/
int (*info_callback) (const WOLFCRYPT_BIO *bio, int state, int ret);
} WOLFCRYPT_BIO_CONNECT;
static int WOLFCRYPT_BIO_conn_state(WOLFCRYPT_BIO *bio,
WOLFCRYPT_BIO_CONNECT *conn)
{
int ret = -1, i;
word32 l;
char *p, *q;
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_state");
if (bio == NULL || conn == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
for (;;) {
switch (conn->state) {
case BIO_CONN_S_BEFORE:
p = conn->pHostname;
if (p == NULL) {
WOLFSSL_ERROR(BIO_NO_HOSTNAME_E);
goto exit_loop;
}
for (; *p != '\0'; p++) {
if ((*p == ':') || (*p == '/'))
break;
}
i = *p;
if ((i == ':') || (i == '/')) {
*(p++) = '\0';
if (i == ':') {
for (q = p; *q; q++)
if (*q == '/') {
*q = '\0';
break;
}
if (conn->pPort != NULL)
XFREE(conn->pPort, 0, DYNAMIC_TYPE_OPENSSL);
conn->pPort = XMALLOC(strlen(p)+1,
0, DYNAMIC_TYPE_OPENSSL);
if (conn->pPort == NULL) {
WOLFSSL_ERROR(MEMORY_E);
goto exit_loop;
break;
}
XSTRNCPY(conn->pPort, p, strlen(p)+1);
}
}
if (conn->pPort == NULL) {
WOLFSSL_ERROR(BIO_NO_PORT_E);
goto exit_loop;
}
conn->state = BIO_CONN_S_GET_IP;
break;
case BIO_CONN_S_GET_IP:
if (WOLFCRYPT_BIO_get_host_ip(conn->pHostname,
conn->ip) <= 0)
goto exit_loop;
conn->state = BIO_CONN_S_GET_PORT;
break;
case BIO_CONN_S_GET_PORT:
if (conn->pPort == NULL ||
WOLFCRYPT_BIO_get_port(conn->pPort, &conn->port) <= 0)
goto exit_loop;
conn->state = BIO_CONN_S_CREATE_SOCKET;
break;
case BIO_CONN_S_CREATE_SOCKET:
/* now setup address */
XMEMSET(&conn->them, 0, sizeof(conn->them));
conn->them.sin_family = AF_INET;
conn->them.sin_port = htons((unsigned short)conn->port);
l = ((word32)conn->ip[0] << 24L) |
((word32)conn->ip[1] << 16L) |
((word32)conn->ip[2] << 8L) |
((word32)conn->ip[3]);
conn->them.sin_addr.s_addr = htonl(l);
conn->state = BIO_CONN_S_CREATE_SOCKET;
ret = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ret <= 0) {
WOLFSSL_ERROR(BIO_CREATE_SOCKET_E);
goto exit_loop;
}
bio->num = ret;
conn->state = BIO_CONN_S_NBIO;
break;
case BIO_CONN_S_NBIO:
if (conn->nbio) {
if (!WOLFCRYPT_BIO_socket_nbio(bio->num, 1)) {
WOLFSSL_ERROR(BIO_NBIO_E);
goto exit_loop;
}
}
conn->state = BIO_CONN_S_CONNECT;
# if defined(SO_KEEPALIVE)
i = 1;
i = setsockopt(bio->num, SOL_SOCKET, SO_KEEPALIVE, (char *)&i,
sizeof(i));
if (i < 0) {
WOLFSSL_ERROR(BIO_KEEPALIVE_E);
goto exit_loop;
}
# endif
break;
case BIO_CONN_S_CONNECT:
WOLFCRYPT_BIO_clear_retry_flags(bio);
ret = connect(bio->num, (struct sockaddr *)&conn->them,
sizeof(conn->them));
bio->retry_reason = 0;
if (ret < 0) {
if (WOLFCRYPT_BIO_sock_should_retry(ret)) {
WOLFCRYPT_BIO_set_retry_special(bio);
conn->state = BIO_CONN_S_BLOCKED_CONNECT;
bio->retry_reason = BIO_RR_CONNECT;
}
else
WOLFSSL_ERROR(BIO_CONNECT_E);
goto exit_loop;
}
else
conn->state = BIO_CONN_S_OK;
break;
case BIO_CONN_S_BLOCKED_CONNECT:
i = WOLFCRYPT_BIO_sock_error(bio->num);
if (i != 0) {
WOLFSSL_ERROR(BIO_CONNECT_E);
ret = 0;
goto exit_loop;
}
else
conn->state = BIO_CONN_S_OK;
break;
case BIO_CONN_S_OK:
ret = 1;
goto exit_loop;
break;
default:
goto exit_loop;
break;
}
if (conn->info_callback != NULL) {
ret = conn->info_callback(bio, conn->state, ret);
if (!ret)
goto end;
}
}
exit_loop:
if (conn->info_callback != NULL)
ret = conn->info_callback(bio, conn->state, ret);
end:
return ret;
}
static WOLFCRYPT_BIO_CONNECT *WOLFCRYPT_BIO_CONNECT_new(void)
{
WOLFCRYPT_BIO_CONNECT *conn;
WOLFSSL_ENTER("WOLFCRYPT_BIO_CONNECT_new");
conn = (WOLFCRYPT_BIO_CONNECT *)XMALLOC(sizeof(WOLFCRYPT_BIO_CONNECT),
0, DYNAMIC_TYPE_OPENSSL);
if (conn == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return NULL;
}
XMEMSET(conn, 0, sizeof(WOLFCRYPT_BIO_CONNECT));
conn->state = BIO_CONN_S_BEFORE;
return conn;
}
static void WOLFCRYPT_BIO_CONNECT_free(WOLFCRYPT_BIO_CONNECT *conn)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_CONNECT_free");
if (conn == NULL)
return;
if (conn->pHostname != NULL) {
XFREE(conn->pHostname, 0, DYNAMIC_TYPE_OPENSSL);
conn->pHostname = NULL;
}
if (conn->pPort != NULL) {
XFREE(conn->pPort, 0, DYNAMIC_TYPE_OPENSSL);
conn->pPort = NULL;
}
XFREE(conn, 0, DYNAMIC_TYPE_OPENSSL);
conn = NULL;
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_connect(void)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_s_connect");
return (&WOLFCRYPT_BIO_conn_method);
}
static int WOLFCRYPT_BIO_conn_new(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_new");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
bio->init = 0;
bio->flags = 0;
bio->num = WOLFSSL_SOCKET_INVALID;
bio->ptr = WOLFCRYPT_BIO_CONNECT_new();
if (bio->ptr == NULL)
return 0;
return 1;
}
static void WOLFCRYPT_BIO_conn_close_socket(WOLFCRYPT_BIO *bio)
{
WOLFCRYPT_BIO_CONNECT *conn;
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_close_socket");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return ;
}
conn = (WOLFCRYPT_BIO_CONNECT *)bio->ptr;
if (bio->num > 0) {
/* Only do a shutdown if things were established */
if (conn->state == BIO_CONN_S_OK)
shutdown(bio->num, SHUT_RDWR);
#ifdef USE_WINDOWS_API
closesocket(bio->num);
#else
close(bio->num);
#endif
bio->num = WOLFSSL_SOCKET_INVALID;
}
}
static int WOLFCRYPT_BIO_conn_free(WOLFCRYPT_BIO *bio)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_free");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (bio->shutdown) {
WOLFCRYPT_BIO_conn_close_socket(bio);
WOLFCRYPT_BIO_CONNECT_free((WOLFCRYPT_BIO_CONNECT *)bio->ptr);
bio->ptr = NULL;
bio->flags = 0;
bio->init = 0;
}
return 1;
}
static int WOLFCRYPT_BIO_conn_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = 0;
WOLFCRYPT_BIO_CONNECT *conn;
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_read");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
conn = (WOLFCRYPT_BIO_CONNECT *)bio->ptr;
if (conn->state != BIO_CONN_S_OK) {
ret = WOLFCRYPT_BIO_conn_state(bio, conn);
if (ret <= 0)
return (ret);
}
#ifdef USE_WINDOWS_API
WSASetLastError(0);
ret = (int)recv(bio->num, data, size, 0);
#else
errno = 0;
ret = (int)read(bio->num, data, size);
#endif
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (WOLFCRYPT_BIO_sock_should_retry(ret))
WOLFCRYPT_BIO_set_retry_read(bio);
}
return ret;
}
static int WOLFCRYPT_BIO_conn_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret = 0;
WOLFCRYPT_BIO_CONNECT *conn;
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_write");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
conn = (WOLFCRYPT_BIO_CONNECT *)bio->ptr;
if (conn->state != BIO_CONN_S_OK) {
ret = WOLFCRYPT_BIO_conn_state(bio, conn);
if (ret <= 0)
return (ret);
}
#ifdef USE_WINDOWS_API
WSASetLastError(0);
ret = (int)send(bio->num, data, size, 0);
#else
errno = 0;
ret = (int)write(bio->num, data, size);
#endif
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (WOLFCRYPT_BIO_sock_should_retry(ret))
WOLFCRYPT_BIO_set_retry_write(bio);
}
return ret;
}
static long WOLFCRYPT_BIO_conn_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
long ret = 1;
WOLFCRYPT_BIO_CONNECT *conn;
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_ctrl");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
conn = (WOLFCRYPT_BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
ret = 0;
conn->state = BIO_CONN_S_BEFORE;
WOLFCRYPT_BIO_conn_close_socket(bio);
bio->flags = 0;
break;
case BIO_C_DO_STATE_MACHINE:
/* use this one to start the connection */
if (conn->state != BIO_CONN_S_OK)
ret = (long)WOLFCRYPT_BIO_conn_state(bio, conn);
else
ret = 1;
break;
case BIO_C_GET_CONNECT:
if (ptr == NULL)
break;
if (num == 0)
*((const char **)ptr) = conn->pHostname;
else if (num == 1)
*((const char **)ptr) = conn->pPort;
else if (num == 2)
*((const char **)ptr) = (char *)conn->ip;
else if (num == 3)
*((int *)ptr) = conn->port;
if (!bio->init || ptr == NULL)
*((const char **)ptr) = "not initialized";
ret = 1;
break;
case BIO_C_SET_CONNECT:
if (ptr == NULL)
break;
bio->init = 1;
if (num == 0) {
if (conn->pHostname != NULL)
XFREE(conn->pHostname, 0, DYNAMIC_TYPE_OPENSSL);
conn->pHostname = XMALLOC(strlen((char *)ptr)+1,
0, DYNAMIC_TYPE_OPENSSL);
if (conn->pHostname == NULL) {
WOLFSSL_ERROR(MEMORY_E);
ret = -1;
break;
}
XSTRNCPY(conn->pHostname, (char *)ptr, strlen((char *)ptr)+1);
}
else if (num == 1) {
if (conn->pPort != NULL)
XFREE(conn->pPort, 0, DYNAMIC_TYPE_OPENSSL);
conn->pPort = XMALLOC(strlen((char *)ptr)+1,
0, DYNAMIC_TYPE_OPENSSL);
if (conn->pPort == NULL) {
WOLFSSL_ERROR(MEMORY_E);
ret = -1;
break;
}
XSTRNCPY(conn->pPort, (char *)ptr, strlen((char *)ptr)+1);
}
else if (num == 2) {
char buf[16];
unsigned char *p = ptr;
XSNPRINTF(buf, sizeof(buf), "%d.%d.%d.%d",
p[0], p[1], p[2], p[3]);
if (conn->pHostname != NULL)
XFREE(conn->pHostname, 0, DYNAMIC_TYPE_OPENSSL);
conn->pHostname = XMALLOC(strlen(buf)+1,
0, DYNAMIC_TYPE_OPENSSL);
if (conn->pHostname == NULL) {
WOLFSSL_ERROR(MEMORY_E);
ret = -1;
break;
}
XSTRNCPY(conn->pHostname, buf, strlen(buf)+1);
memcpy(conn->ip, ptr, 4);
}
else if (num == 3) {
char buf[6];
XSNPRINTF(buf, sizeof(buf), "%d", *(int *)ptr);
if (conn->pPort != NULL)
XFREE(conn->pPort, 0, DYNAMIC_TYPE_OPENSSL);
conn->pPort = XMALLOC(strlen(buf)+1,
0, DYNAMIC_TYPE_OPENSSL);
if (conn->pPort == NULL) {
WOLFSSL_ERROR(MEMORY_E);
ret = -1;
break;
}
XSTRNCPY(conn->pPort, buf, strlen(buf)+1);
conn->port = *(int *)ptr;
}
break;
case BIO_C_SET_NBIO:
conn->nbio = (int)num;
break;
case BIO_C_GET_FD:
if (bio->init) {
if (ptr != NULL)
*((int *)ptr) = bio->num;
ret = bio->num;
}
else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_FLUSH:
break;
case BIO_CTRL_DUP:
{
WOLFCRYPT_BIO *dbio = (WOLFCRYPT_BIO *)ptr;
if (conn->pPort != NULL)
WOLFCRYPT_BIO_set_conn_port(dbio, conn->pPort);
if (conn->pHostname != NULL)
WOLFCRYPT_BIO_set_conn_hostname(dbio, conn->pHostname);
WOLFCRYPT_BIO_set_nbio(dbio, conn->nbio);
WOLFCRYPT_BIO_set_info_callback(dbio,
(WOLFCRYPT_BIO_info_cb *)conn->info_callback);
}
break;
case BIO_CTRL_SET_CALLBACK:
ret = 0;
break;
case BIO_CTRL_GET_CALLBACK:
{
int (**fptr) (const WOLFCRYPT_BIO *bio, int state, int xret);
fptr = (int (**)(const WOLFCRYPT_BIO *bio,
int state, int xret))ptr;
*fptr = conn->info_callback;
}
break;
default:
ret = 0;
break;
}
return ret;
}
static long WOLFCRYPT_BIO_conn_callback_ctrl(WOLFCRYPT_BIO *bio,
int cmd, WOLFCRYPT_BIO_info_cb *fp)
{
long ret = 1;
WOLFCRYPT_BIO_CONNECT *conn;
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_callback_ctrl");
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
conn = (WOLFCRYPT_BIO_CONNECT *)bio->ptr;
switch (cmd) {
case BIO_CTRL_SET_CALLBACK:
conn->info_callback = (int (*)(const WOLFCRYPT_BIO *, int, int))fp;
break;
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_conn_puts(WOLFCRYPT_BIO *bio, const char *str)
{
WOLFSSL_ENTER("WOLFCRYPT_BIO_conn_puts");
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
return WOLFCRYPT_BIO_conn_write(bio, str, (int)strlen(str));
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_connect(const char *str)
{
WOLFCRYPT_BIO *bio;
WOLFSSL_ENTER("WOLFCRYPT_BIO_new_connect");
if (str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_connect());
if (bio == NULL)
return NULL;
if (WOLFCRYPT_BIO_set_conn_hostname(bio, str))
return bio;
WOLFCRYPT_BIO_free(bio);
return NULL;
}
#endif /* OPENSSL_EXTRA */

795
wolfcrypt/src/bio_m_dgram.c Normal file
View File

@@ -0,0 +1,795 @@
/* bio_m_dgram.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#ifdef USE_WINDOWS_API
#include <winsock2.h>
#include <process.h>
#else
#include <sys/time.h>
#endif /* USE_WINDOWS_API */
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
/* Socket Handling */
#ifndef WOLFSSL_SOCKET_INVALID
#ifdef USE_WINDOWS_API
#define WOLFSSL_SOCKET_INVALID ((SOCKET)WOLFSSL_SOCKET_INVALID)
#else
#define WOLFSSL_SOCKET_INVALID (0)
#endif
#endif /* WOLFSSL_SOCKET_INVALID */
#if !defined(IP_MTU)
#define IP_MTU 14
#endif
#if defined(TEST_IPV6) && !defined(IPPROTO_IPV6)
#define IPPROTO_IPV6 41
#endif
static int WOLFCRYPT_BIO_DATAGRAM_write(WOLFCRYPT_BIO *bio,
const char *data, int size);
static int WOLFCRYPT_BIO_DATAGRAM_read(WOLFCRYPT_BIO *bio, char *data, int size);
static int WOLFCRYPT_BIO_DATAGRAM_puts(WOLFCRYPT_BIO *bio, const char *str);
static long WOLFCRYPT_BIO_DATAGRAM_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr);
static int WOLFCRYPT_BIO_DATAGRAM_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_DATAGRAM_free(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_DATAGRAM_clear(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_DATAGRAM_should_retry(int s);
static void get_current_time(struct timeval *t);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_dgram_method = {
BIO_TYPE_DGRAM,
"Datagram socket",
WOLFCRYPT_BIO_DATAGRAM_write,
WOLFCRYPT_BIO_DATAGRAM_read,
WOLFCRYPT_BIO_DATAGRAM_puts,
NULL, /* gets */
WOLFCRYPT_BIO_DATAGRAM_ctrl,
WOLFCRYPT_BIO_DATAGRAM_new,
WOLFCRYPT_BIO_DATAGRAM_free,
NULL,
};
typedef struct {
union {
struct sockaddr sa;
struct sockaddr_in sa_in;
#ifdef TEST_IPV6
struct sockaddr_in6 sa_in6;
# endif
} peer;
unsigned int connected;
unsigned int _errno;
unsigned int mtu;
struct timeval next_timeout;
struct timeval socket_timeout;
} WOLFCRYPT_BIO_DATAGRAM;
static int WOLFCRYPT_BIO_DATAGRAM_should_retry(int i)
{
if (!i || i == -1) {
int ret;
#ifdef USE_WINDOWS_API
ret = WSAGetLastError();
#else
ret = errno;
#endif
return WOLCRYPT_BIO_sock_non_fatal_error(ret);
}
return 0;
}
static void get_current_time(struct timeval *t)
{
#ifdef USE_WINDOWS_API
SYSTEMTIME st;
union {
unsigned __int64 ul;
FILETIME ft;
} now;
GetSystemTime(&st);
SystemTimeToFileTime(&st, &now.ft);
now.ul -= 116444736000000000UI64; /* re-bias to 1/1/1970 */
t->tv_sec = (long)(now.ul / 10000000);
t->tv_usec = ((int)(now.ul % 10000000)) / 10;
# else
gettimeofday(t, NULL);
# endif
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_datagram(void)
{
return (&WOLFCRYPT_BIO_dgram_method);
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_dgram(int fd, int close_flag)
{
WOLFCRYPT_BIO *bio;
bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_datagram());
if (bio == NULL)
return NULL;
WOLFCRYPT_BIO_set_fd(bio, fd, close_flag);
return bio;
}
static int WOLFCRYPT_BIO_DATAGRAM_new(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
bio->init = 0;
bio->num = 0;
bio->flags = 0;
bio->ptr = XMALLOC(sizeof(WOLFCRYPT_BIO_DATAGRAM), 0, DYNAMIC_TYPE_OPENSSL);
if (bio->ptr == NULL)
return 0;
XMEMSET(bio->ptr, 0, sizeof(WOLFCRYPT_BIO_DATAGRAM));
return 1;
}
static int WOLFCRYPT_BIO_DATAGRAM_free(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (!WOLFCRYPT_BIO_DATAGRAM_clear(bio))
return 0;
if (bio->ptr != NULL)
XFREE(bio->ptr, 0, DYNAMIC_TYPE_OPENSSL);
return 1;
}
static int WOLFCRYPT_BIO_DATAGRAM_clear(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (bio->shutdown) {
if (bio->init) {
shutdown(bio->num, SHUT_RDWR);
#ifdef USE_WINDOWS_API
closesocket(bio->num);
#else
close(bio->num);
#endif
}
bio->init = 0;
bio->flags = 0;
}
return 1;
}
static void WOLFCRYPT_BIO_DATAGRAM_adjust_rcv_timeout(WOLFCRYPT_BIO *bio)
{
#ifdef SO_RCVTIMEO
WOLFCRYPT_BIO_DATAGRAM *dgram;
union {
size_t s;
int i;
} sz = { 0 };
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return;
}
dgram = (WOLFCRYPT_BIO_DATAGRAM *)bio->ptr;
/* Is a timer active? */
if (dgram->next_timeout.tv_sec > 0 || dgram->next_timeout.tv_usec > 0) {
struct timeval timenow, timeleft;
/* Read current socket timeout */
#ifdef USE_WINDOWS_API
int timeout;
sz.i = sizeof(timeout);
if (getsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timeout, &sz.i) >= 0) {
dgram->socket_timeout.tv_sec = timeout / 1000;
dgram->socket_timeout.tv_usec = (timeout % 1000) * 1000;
}
#else
sz.i = sizeof(dgram->socket_timeout);
if (getsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
&(dgram->socket_timeout), (void *)&sz) >= 0) {
if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0)
if (sz.s > sizeof(dgram->socket_timeout))
return ;
}
#endif /* USE_WINDOWS_API */
/* Get current time */
get_current_time(&timenow);
/* Calculate time left until timer expires */
XMEMCPY(&timeleft, &dgram->next_timeout, sizeof(struct timeval));
if (timeleft.tv_usec < timenow.tv_usec) {
timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec;
timeleft.tv_sec--;
}
else
timeleft.tv_usec -= timenow.tv_usec;
if (timeleft.tv_sec < timenow.tv_sec) {
timeleft.tv_sec = 0;
timeleft.tv_usec = 1;
}
else
timeleft.tv_sec -= timenow.tv_sec;
/*
* Adjust socket timeout if next handhake message timer will expire
* earlier.
*/
if ((!dgram->socket_timeout.tv_sec && !dgram->socket_timeout.tv_usec) ||
(dgram->socket_timeout.tv_sec > timeleft.tv_sec) ||
(dgram->socket_timeout.tv_sec == timeleft.tv_sec &&
dgram->socket_timeout.tv_usec >= timeleft.tv_usec)) {
#ifdef USE_WINDOWS_API
timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
setsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timeout, sizeof(timeout));
#else
setsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
sizeof(struct timeval));
#endif /* USE_WINDOWS_API */
}
}
#endif /* SO_RCVTIMEO */
}
static void WOLFCRYPT_BIO_DATAGRAM_reset_rcv_timeout(WOLFCRYPT_BIO *bio)
{
#if defined(SO_RCVTIMEO)
WOLFCRYPT_BIO_DATAGRAM *dgram;
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return;
}
dgram = (WOLFCRYPT_BIO_DATAGRAM *)bio->ptr;
/* Is a timer active? */
if (dgram->next_timeout.tv_sec > 0 || dgram->next_timeout.tv_usec > 0) {
#ifdef USE_WINDOWS_API
int timeout = dgram->socket_timeout.tv_sec * 1000 +
dgram->socket_timeout.tv_usec / 1000;
setsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timeout, sizeof(timeout));
#else
setsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO, &(dgram->socket_timeout),
sizeof(struct timeval));
#endif
}
#endif
}
static int WOLFCRYPT_BIO_DATAGRAM_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = 0;
WOLFCRYPT_BIO_DATAGRAM *dgram;
struct {
union {
size_t s;
int i;
} len;
union {
struct sockaddr sa;
struct sockaddr_in sa_in;
#ifdef TEST_IPV6
struct sockaddr_in6 sa_in6;
#endif
} peer;
} sa;
if (bio == NULL || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
dgram = (WOLFCRYPT_BIO_DATAGRAM *)bio->ptr;
sa.len.s = 0;
sa.len.i = sizeof(sa.peer);
#ifdef USE_WINDOWS_API
WSASetLastError(0);
#else
errno = 0;
#endif
XMEMSET(&sa.peer, 0, sizeof(sa.peer));
WOLFCRYPT_BIO_DATAGRAM_adjust_rcv_timeout(bio);
ret = (int)recvfrom(bio->num, data, size, 0, &sa.peer.sa, (void *)&sa.len);
if (sizeof(sa.len.i) != sizeof(sa.len.s) && sa.len.i == 0) {
if (sa.len.s > sizeof(sa.peer))
return 0;
sa.len.i = (int)sa.len.s;
}
if (!dgram->connected && ret >= 0)
WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_DGRAM_SET_PEER, 0, &sa.peer);
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ret < 0) {
if (WOLFCRYPT_BIO_DATAGRAM_should_retry(ret)) {
WOLFCRYPT_BIO_set_retry_read(bio);
#ifdef USE_WINDOWS_API
dgram->_errno = WSAGetLastError();
#else
dgram->_errno = errno;
#endif
}
}
WOLFCRYPT_BIO_DATAGRAM_reset_rcv_timeout(bio);
return ret;
}
static int WOLFCRYPT_BIO_DATAGRAM_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret;
WOLFCRYPT_BIO_DATAGRAM *dgram;
if (bio == NULL || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
dgram = (WOLFCRYPT_BIO_DATAGRAM *)bio->ptr;
#ifdef USE_WINDOWS_API
WSASetLastError(0);
#else
errno = 0;
#endif
if (dgram->connected)
#ifdef USE_WINDOWS_API
ret = (int)send(bio->num, data, size, 0);
#else
ret = (int)write(bio->num, data, size);
#endif
else {
int peerlen = sizeof(dgram->peer);
if (dgram->peer.sa.sa_family == AF_INET)
peerlen = sizeof(dgram->peer.sa_in);
#ifdef TEST_IPV6
else if (dgram->peer.sa.sa_family == AF_INET6)
peerlen = sizeof(dgram->peer.sa_in6);
#endif
ret = (int)sendto(bio->num, data, size, 0, &dgram->peer.sa, peerlen);
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ret <= 0 && WOLFCRYPT_BIO_DATAGRAM_should_retry(ret)) {
WOLFCRYPT_BIO_set_retry_write(bio);
#ifdef USE_WINDOWS_API
dgram->_errno = WSAGetLastError();
#else
dgram->_errno = errno;
#endif
}
return ret;
}
static long WOLFCRYPT_BIO_DATAGRAM_get_mtu_overhead(WOLFCRYPT_BIO_DATAGRAM *dgram)
{
long ret;
if (dgram == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
switch (dgram->peer.sa.sa_family) {
case AF_INET:
ret = 28;
break;
#ifdef TEST_IPV6
case AF_INET6:
ret = 48;
break;
#endif
default:
ret = 28;
break;
}
return ret;
}
static long WOLFCRYPT_BIO_DATAGRAM_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
long ret = 1;
struct sockaddr *to = NULL;
WOLFCRYPT_BIO_DATAGRAM *dgram;
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
dgram = (WOLFCRYPT_BIO_DATAGRAM *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
num = 0;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
case BIO_C_FILE_SEEK:
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = 0;
break;
case BIO_C_SET_FD:
WOLFCRYPT_BIO_DATAGRAM_clear(bio);
bio->num = *((int *)ptr);
bio->shutdown = (int)num;
bio->init = 1;
break;
case BIO_C_GET_FD:
if (bio->init) {
if (ptr != NULL)
*((int *)ptr) = bio->num;
ret = bio->num;
}
else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
case BIO_CTRL_DGRAM_CONNECT:
to = (struct sockaddr *)ptr;
switch (to->sa_family) {
case AF_INET:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa_in));
break;
#ifdef TEST_IPV6
case AF_INET6:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa_in6));
break;
#endif
default:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa));
break;
}
break;
/* (Linux)kernel sets DF bit on outgoing IP packets */
case BIO_CTRL_DGRAM_MTU_DISCOVER:
break;
case BIO_CTRL_DGRAM_QUERY_MTU:
ret = 0;
break;
case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
ret = -WOLFCRYPT_BIO_DATAGRAM_get_mtu_overhead(dgram);
switch (dgram->peer.sa.sa_family) {
case AF_INET:
ret += 576;
break;
#ifdef TEST_IPV6
case AF_INET6:
ret += 1280;
break;
#endif
default:
ret += 576;
break;
}
break;
case BIO_CTRL_DGRAM_GET_MTU:
return dgram->mtu;
break;
case BIO_CTRL_DGRAM_SET_MTU:
dgram->mtu = (int)num;
ret = num;
break;
case BIO_CTRL_DGRAM_SET_CONNECTED:
to = (struct sockaddr *)ptr;
if (to != NULL) {
dgram->connected = 1;
switch (to->sa_family) {
case AF_INET:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa_in));
break;
#ifdef TEST_IPV6
case AF_INET6:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa_in6));
break;
#endif
default:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa));
break;
}
}
else {
dgram->connected = 0;
XMEMSET(&dgram->peer, 0, sizeof(dgram->peer));
}
break;
case BIO_CTRL_DGRAM_GET_PEER:
switch (dgram->peer.sa.sa_family) {
case AF_INET:
ret = sizeof(dgram->peer.sa_in);
break;
#ifdef TEST_IPV6
case AF_INET6:
ret = sizeof(dgram->peer.sa_in6);
break;
#endif
default:
ret = sizeof(dgram->peer.sa);
break;
}
if (num == 0 || num > ret)
num = ret;
XMEMCPY(ptr, &dgram->peer, (ret = num));
break;
case BIO_CTRL_DGRAM_SET_PEER:
to = (struct sockaddr *)ptr;
switch (to->sa_family) {
case AF_INET:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa_in));
break;
#ifdef TEST_IPV6
case AF_INET6:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa_in6));
break;
#endif
default:
XMEMCPY(&dgram->peer, to, sizeof(dgram->peer.sa));
break;
}
break;
case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
XMEMCPY(&dgram->next_timeout, ptr, sizeof(struct timeval));
break;
#if defined(SO_RCVTIMEO)
case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
#ifdef USE_WINDOWS_API
{
struct timeval *tv = (struct timeval *)ptr;
int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
if (setsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timeout, sizeof(timeout)) < 0)
ret = -1;
}
#else
if (setsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
sizeof(struct timeval)) < 0)
ret = -1;
#endif /* USE_WINDOWS_API */
break;
case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
{
union {
size_t s;
int i;
} sz = { 0 };
#ifdef USE_WINDOWS_API
int timeout;
struct timeval *tv = (struct timeval *)ptr;
sz.i = sizeof(timeout);
if (getsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timeout, &sz.i) < 0)
ret = -1;
else {
tv->tv_sec = timeout / 1000;
tv->tv_usec = (timeout % 1000) * 1000;
ret = sizeof(*tv);
}
#else
sz.i = sizeof(struct timeval);
if (getsockopt(bio->num, SOL_SOCKET, SO_RCVTIMEO,
ptr, (void *)&sz) < 0)
ret = -1;
else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
if (sz.s > sizeof(struct timeval))
ret = -1;
else
ret = (int)sz.s;
}
else
ret = sz.i;
#endif /* USE_WINDOWS_API */
}
break;
# endif /* defined(SO_RCVTIMEO) */
# if defined(SO_SNDTIMEO)
case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
#ifdef USE_WINDOWS_API
{
struct timeval *tv = (struct timeval *)ptr;
int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000;
if (setsockopt(bio->num, SOL_SOCKET, SO_SNDTIMEO,
(void *)&timeout, sizeof(timeout)) < 0)
ret = -1;
}
#else
if (setsockopt(bio->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
sizeof(struct timeval)) < 0)
ret = -1;
#endif /* USE_WINDOWS_API */
break;
case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
{
union {
size_t s;
int i;
} sz = { 0 };
#ifdef USE_WINDOWS_API
int timeout;
struct timeval *tv = (struct timeval *)ptr;
sz.i = sizeof(timeout);
if (getsockopt(bio->num, SOL_SOCKET, SO_SNDTIMEO,
(void *)&timeout, &sz.i) < 0)
ret = -1;
else {
tv->tv_sec = timeout / 1000;
tv->tv_usec = (timeout % 1000) * 1000;
ret = sizeof(*tv);
}
#else
sz.i = sizeof(struct timeval);
if (getsockopt(bio->num, SOL_SOCKET, SO_SNDTIMEO,
ptr, (void *)&sz) < 0)
ret = -1;
else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
if (sz.s > sizeof(struct timeval))
ret = -1;
else
ret = (int)sz.s;
}
else
ret = sz.i;
#endif /* USE_WINDOWS_API */
}
break;
#endif /* defined(SO_SNDTIMEO) */
case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
#ifdef USE_WINDOWS_API
if (dgram->_errno == WSAETIMEDOUT)
#else
if (dgram->_errno == EAGAIN)
#endif
{
ret = 1;
dgram->_errno = 0;
}
else
ret = 0;
break;
case BIO_CTRL_DGRAM_SET_DONT_FRAG:
ret = -1;
break;
case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
ret = WOLFCRYPT_BIO_DATAGRAM_get_mtu_overhead(dgram);
break;
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_DATAGRAM_puts(WOLFCRYPT_BIO *bio, const char *str)
{
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
return WOLFCRYPT_BIO_DATAGRAM_write(bio, str, (int)strlen(str));
}
#endif /* OPENSSL_EXTRA */

145
wolfcrypt/src/bio_m_fd.c Normal file
View File

@@ -0,0 +1,145 @@
/* bio_m_fd.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
static int WOLFCRYPT_BIO_fd_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_fd_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_fd_puts(WOLFCRYPT_BIO *bio, const char *str);
static int WOLFCRYPT_BIO_fd_gets(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_fd_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_fd_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_fd_free(WOLFCRYPT_BIO *bio);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_fd_method = {
BIO_TYPE_FD,
"File descriptor",
WOLFCRYPT_BIO_fd_write,
WOLFCRYPT_BIO_fd_read,
WOLFCRYPT_BIO_fd_puts,
WOLFCRYPT_BIO_fd_gets,
WOLFCRYPT_BIO_fd_ctrl,
WOLFCRYPT_BIO_fd_new,
WOLFCRYPT_BIO_fd_free,
NULL,
};
/* functions are not implemented as not really used in OpenSSL except for two
* cases :
* * get password giving 'fd file' instead of 'file name'
* (see app_get_pass(), apps/apps.c)
* * open STDOUT and STDERR by giving fd instead of name
* (see main(), crypto/threads/mttest.c)
*/
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_fd(void)
{
WOLFSSL_ERROR(NOT_COMPILED_IN);
return (&WOLFCRYPT_BIO_fd_method);
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_fd(int fd, int close_flag)
{
(void)fd;
(void)close_flag;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return NULL;
}
static int WOLFCRYPT_BIO_fd_new(WOLFCRYPT_BIO *bio)
{
(void)bio;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
static int WOLFCRYPT_BIO_fd_free(WOLFCRYPT_BIO *bio)
{
(void)bio;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
static int WOLFCRYPT_BIO_fd_read(WOLFCRYPT_BIO *bio, char *buf, int size)
{
(void)bio;
(void)buf;
(void)size;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
static int WOLFCRYPT_BIO_fd_write(WOLFCRYPT_BIO *bio, const char *buf, int size)
{
(void)bio;
(void)buf;
(void)size;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
static long WOLFCRYPT_BIO_fd_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr)
{
(void)bio;
(void)ptr;
(void)cmd;
(void)num;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
static int WOLFCRYPT_BIO_fd_gets(WOLFCRYPT_BIO *bio, char *buf, int size)
{
(void)bio;
(void)buf;
(void)size;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
static int WOLFCRYPT_BIO_fd_puts(WOLFCRYPT_BIO *bio, const char *str)
{
(void)bio;
(void)str;
WOLFSSL_ERROR(NOT_COMPILED_IN);
return -2;
}
#endif /* OPENSSL_EXTRA */

357
wolfcrypt/src/bio_m_file.c Normal file
View File

@@ -0,0 +1,357 @@
/* bio_m_file.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#ifndef NO_FILESYSTEM
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/openssl/bio.h>
/* TO BE REMOVED */
#ifndef XFERROR
#define XFERROR ferror
#endif
#ifndef XFILENO
#define XFILENO fileno
#endif
#if defined(USE_WINDOWS_API)
#include <io.h>
#ifndef XSETMODE
#define XSETMODE _setmode
#endif
#endif /* USE_WINDOWS_API */
#ifndef XFFLUSH
#define XFFLUSH fflush
#endif
#ifndef XFEOF
#define XFEOF feof
#endif
#ifndef XFGETS
#define XFGETS fgets
#endif
static int WOLFCRYPT_BIO_file_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_file_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_file_puts(WOLFCRYPT_BIO *bio, const char *str);
static int WOLFCRYPT_BIO_file_gets(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_file_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_file_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_file_free(WOLFCRYPT_BIO *bio);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_file_method = {
BIO_TYPE_FILE,
"FILE pointer",
WOLFCRYPT_BIO_file_write,
WOLFCRYPT_BIO_file_read,
WOLFCRYPT_BIO_file_puts,
WOLFCRYPT_BIO_file_gets,
WOLFCRYPT_BIO_file_ctrl,
WOLFCRYPT_BIO_file_new,
WOLFCRYPT_BIO_file_free,
NULL,
};
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_file(const char *name, const char *mode)
{
XFILE f;
if (name == NULL || mode == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
f = XFOPEN(name, mode);
if (f == NULL) {
WOLFSSL_ERROR(BIO_FILE_OPEN_E);
return NULL;
}
return WOLFCRYPT_BIO_new_fp(f, BIO_CLOSE);
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_fp(XFILE f, int close_flag)
{
WOLFCRYPT_BIO *bio;
if (f == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_file());
if (bio == NULL)
return NULL;
WOLFCRYPT_BIO_set_fp(bio, f, close_flag);
return bio;
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_file(void)
{
return (&WOLFCRYPT_BIO_file_method);
}
static int WOLFCRYPT_BIO_file_new(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bio->init = 0;
bio->num = 0;
bio->ptr = NULL;
return 1;
}
static int WOLFCRYPT_BIO_file_free(WOLFCRYPT_BIO *bio)
{
if (bio == NULL)
return 0;
if (!bio->shutdown || !bio->init)
return 1;
if (bio->ptr != NULL) {
XFCLOSE(bio->ptr);
bio->ptr = NULL;
}
bio->init = 0;
return 1;
}
static int WOLFCRYPT_BIO_file_read(WOLFCRYPT_BIO *bio, char *buf, int size)
{
int ret = 0;
if (bio == NULL || !bio->init || bio->ptr == NULL || buf == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
ret = (int)XFREAD(buf, sizeof(char), size, (FILE *)bio->ptr);
if (ret == 0 && XFERROR((FILE *)bio->ptr)) {
WOLFSSL_ERROR(BIO_FILE_READ_E);
ret = -1;
}
return ret;
}
static int WOLFCRYPT_BIO_file_write(WOLFCRYPT_BIO *bio, const char *buf, int size)
{
int ret = 0;
if (bio == NULL || !bio->init || bio->ptr == NULL || buf == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
ret = (int)XFWRITE(buf, sizeof(char), size, (FILE *)bio->ptr);
if (ret == 0 && XFERROR((FILE *)bio->ptr)) {
WOLFSSL_ERROR(BIO_FILE_WRITE_E);
ret = -1;
}
return ret;
}
static long WOLFCRYPT_BIO_file_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
long ret = 1;
char buf[4];
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
switch (cmd) {
case BIO_C_FILE_SEEK:
case BIO_CTRL_RESET:
ret = (long)XFSEEK((FILE *)bio->ptr, num, 0);
break;
case BIO_CTRL_EOF:
ret = (long)XFEOF((FILE *)bio->ptr);
break;
case BIO_C_FILE_TELL:
case BIO_CTRL_INFO:
ret = (long)XFTELL((FILE *)bio->ptr);
break;
case BIO_C_SET_FILE_PTR:
WOLFCRYPT_BIO_file_free(bio);
bio->shutdown = (int)num & BIO_CLOSE;
bio->ptr = ptr;
bio->init = 1;
#ifdef USE_WINDOWS_API
{
int fd;
fd = XFILENO((FILE *)bio->ptr);
if (num & BIO_FP_TEXT)
XSETMODE(fd, O_TEXT);
else
XSETMODE(fd, O_BINARY);
}
#endif /* USE_WINDOWS_API */
break;
case BIO_C_SET_FILENAME:
WOLFCRYPT_BIO_file_free(bio);
bio->shutdown = (int)num & BIO_CLOSE;
if (num & BIO_FP_APPEND) {
if (num & BIO_FP_READ)
XSTRNCPY(buf, "a+", sizeof(buf) - 1);
else
XSTRNCPY(buf, "a", sizeof(buf) - 1);
}
else if (num & BIO_FP_READ) {
if (num & BIO_FP_WRITE)
XSTRNCPY(buf, "r+", sizeof(buf) - 1);
else
XSTRNCPY(buf, "r", sizeof(buf));
}
else if (num & BIO_FP_WRITE)
XSTRNCPY(buf, "w", sizeof(buf) - 1);
else {
WOLFSSL_ERROR(BIO_FILE_MODE_E);
ret = 0;
break;
}
if (num & BIO_FP_TEXT)
XSTRNCAT(buf, "t", sizeof(buf) - 1);
else
XSTRNCAT(buf, "b", sizeof(buf) - 1);
bio->ptr = XFOPEN(ptr, buf);
if (bio->ptr == NULL) {
WOLFSSL_ERROR(BIO_FILE_OPEN_E);
ret = 0;
break;
}
bio->init = 1;
break;
case BIO_C_GET_FILE_PTR:
/* the ptr parameter is a FILE ** in this case. */
if (ptr != NULL)
*((FILE **)ptr) = (FILE *)bio->ptr;
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_FLUSH:
XFFLUSH((FILE *)bio->ptr);
break;
case BIO_CTRL_DUP:
ret = 1;
break;
case BIO_CTRL_WPENDING:
case BIO_CTRL_PENDING:
case BIO_CTRL_PUSH:
case BIO_CTRL_POP:
ret = 0;
break;
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_file_gets(WOLFCRYPT_BIO *bio, char *buf, int size)
{
if (bio == NULL || bio->ptr == NULL || buf == NULL || size <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
/* init buffer */
XMEMSET(buf, 0, size);
if ((XFGETS(buf, size, (FILE *)bio->ptr) == NULL) &&
XFERROR((FILE *)bio->ptr)) {
WOLFSSL_ERROR(BIO_FILE_GETS_E);
return -1;
}
return (int)strlen(buf);
}
static int WOLFCRYPT_BIO_file_puts(WOLFCRYPT_BIO *bio, const char *str)
{
if (bio == NULL || bio->ptr == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
return WOLFCRYPT_BIO_file_write(bio, str, (int)strlen(str));
}
#endif /* NO_FILESYSTEM */
#endif /* OPENSSL_EXTRA */

423
wolfcrypt/src/bio_m_mem.c Normal file
View File

@@ -0,0 +1,423 @@
/* bio_m_mem.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/openssl/bio.h>
/* wolfSSL buffer type */
typedef struct {
byte* data;
word32 length;
} WOLFCRYPT_BUF_MEM;
static WOLFCRYPT_BUF_MEM *WOLFCRYPT_BUF_MEM_new(void)
{
WOLFCRYPT_BUF_MEM *buf;
buf = (WOLFCRYPT_BUF_MEM *)XMALLOC(sizeof(WOLFCRYPT_BUF_MEM),
0, DYNAMIC_TYPE_OPENSSL);
if (buf == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return NULL;
}
buf->length = 0;
buf->data = NULL;
return buf;
}
static void WOLFCRYPT_BUF_MEM_free(WOLFCRYPT_BUF_MEM *buf)
{
if (buf == NULL)
return;
if (buf->data != NULL) {
XMEMSET(buf->data, 0, buf->length);
XFREE(buf->data, 0, DYNAMIC_TYPE_OPENSSL);
}
XFREE(buf, 0, DYNAMIC_TYPE_OPENSSL);
}
static int WOLFCRYPT_BUF_MEM_grow(WOLFCRYPT_BUF_MEM *buf, size_t len)
{
if (buf == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
/* size reduction, clean unused */
if (buf->length >= len) {
if (buf->data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
buf->length = (word32)len;
return (int)len;
}
if (buf->data == NULL)
buf->data = XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL);
else
buf->data = XREALLOC(buf->data, buf->length+len,
0, DYNAMIC_TYPE_OPENSSL);
if (buf->data == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return -1;
}
XMEMSET(&buf->data[buf->length], 0, len - buf->length);
buf->length = (word32)len;
return (int)len;
}
static int WOLFCRYPT_BUF_MEM_grow_clean(WOLFCRYPT_BUF_MEM *buf, size_t len)
{
int ret, idx = -1;
size_t size;
if (buf == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
if (buf->length >= len) {
idx = buf->length;
size = buf->length - len;
}
ret = WOLFCRYPT_BUF_MEM_grow(buf, len);
if (ret && idx != -1)
XMEMSET(&buf->data[idx], 0, size);
return ret;
}
static int WOLFCRYPT_BIO_mem_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_mem_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_mem_puts(WOLFCRYPT_BIO *bio, const char *str);
static int WOLFCRYPT_BIO_mem_gets(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_mem_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_mem_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_mem_free(WOLFCRYPT_BIO *bio);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_mem_method = {
BIO_TYPE_MEM,
"Memory buffer",
WOLFCRYPT_BIO_mem_write,
WOLFCRYPT_BIO_mem_read,
WOLFCRYPT_BIO_mem_puts,
WOLFCRYPT_BIO_mem_gets,
WOLFCRYPT_BIO_mem_ctrl,
WOLFCRYPT_BIO_mem_new,
WOLFCRYPT_BIO_mem_free,
NULL,
};
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_mem_buf(void *data, int len)
{
WOLFCRYPT_BIO *bio;
size_t size;
if (data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return NULL;
}
size = (len < 0) ? strlen((char *)data) : (size_t)len;
bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_mem());
if (bio == NULL)
return NULL;
((WOLFCRYPT_BUF_MEM *)bio->ptr)->data = (byte*)data;
((WOLFCRYPT_BUF_MEM *)bio->ptr)->length = (word32)size;
bio->flags |= BIO_FLAGS_MEM_RDONLY;
bio->num = 0;
return bio;
}
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_mem(void)
{
return (&WOLFCRYPT_BIO_mem_method);
}
static int WOLFCRYPT_BIO_mem_new(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bio->ptr = WOLFCRYPT_BUF_MEM_new();
if (bio->ptr == NULL)
return -1;
bio->shutdown = 1;
bio->init = 1;
bio->num = -1;
return 1;
}
static int WOLFCRYPT_BIO_mem_free(WOLFCRYPT_BIO *bio)
{
if (bio == NULL)
return -1;
if (!bio->shutdown || !bio->init)
return 1;
if (bio->ptr != NULL) {
if (bio->flags & BIO_FLAGS_MEM_RDONLY)
((WOLFCRYPT_BUF_MEM *)bio->ptr)->data = NULL;
WOLFCRYPT_BUF_MEM_free(bio->ptr);
bio->ptr = NULL;
}
bio->init = 0;
return 1;
}
static int WOLFCRYPT_BIO_mem_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret = -1;
WOLFCRYPT_BUF_MEM *wbmptr;
if (bio == NULL || !bio->init || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
wbmptr = (WOLFCRYPT_BUF_MEM *)bio->ptr;
ret = (size >= 0 && (size_t)size > wbmptr->length) ?
(int)wbmptr->length : size;
if (data != NULL && ret > 0) {
XMEMCPY(data, wbmptr->data, ret);
wbmptr->length -= ret;
if (bio->flags & BIO_FLAGS_MEM_RDONLY)
wbmptr->data += ret;
else
XMEMMOVE(&(wbmptr->data[0]), &(wbmptr->data[ret]), wbmptr->length);
}
else if (wbmptr->length == 0) {
ret = bio->num;
if (ret != 0)
WOLFCRYPT_BIO_set_retry_read(bio);
}
return ret;
}
static int WOLFCRYPT_BIO_mem_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int init_len;
WOLFCRYPT_BUF_MEM *wbmptr;
if (bio == NULL || !bio->init || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
WOLFSSL_ERROR(BIO_MEM_WRITE_E);
return -1;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
wbmptr = (WOLFCRYPT_BUF_MEM *)bio->ptr;
init_len = wbmptr->length;
if (WOLFCRYPT_BUF_MEM_grow_clean(wbmptr, wbmptr->length + size) !=
(int)(init_len + size))
return -1;
XMEMCPY(&(wbmptr->data[init_len]), data, size);
return size;
}
static long WOLFCRYPT_BIO_mem_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
WOLFCRYPT_BUF_MEM *wbmptr;
long ret = 1;
if (bio == NULL || bio->ptr == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
wbmptr = (WOLFCRYPT_BUF_MEM *)bio->ptr;
switch (cmd) {
case BIO_CTRL_RESET:
if (wbmptr->data == NULL)
break;
/* For read only case reset to the start again */
if (bio->flags & BIO_FLAGS_MEM_RDONLY)
wbmptr->data -= wbmptr->length;
else {
XMEMSET(wbmptr->data, 0, wbmptr->length);
wbmptr->length = 0;
}
break;
case BIO_CTRL_EOF:
ret = (long)(wbmptr->length == 0);
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
bio->num = (int)num;
break;
case BIO_CTRL_INFO:
ret = (long)wbmptr->length;
if (ptr != NULL)
*((char **)ptr) = (char *)&(wbmptr->data[0]);
break;
case BIO_C_SET_BUF_MEM:
WOLFCRYPT_BIO_mem_free(bio);
bio->shutdown = (int)num;
bio->ptr = ptr;
break;
case BIO_C_GET_BUF_MEM_PTR:
if (ptr != NULL)
*((char **)ptr) = (char *)wbmptr;
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_PENDING:
ret = (long)wbmptr->length;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
case BIO_CTRL_PUSH:
case BIO_CTRL_POP:
ret = 0;
break;
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_mem_gets(WOLFCRYPT_BIO *bio, char *buf, int size)
{
WOLFCRYPT_BUF_MEM *wbmptr;
int i, blen;
if (bio == NULL || bio->ptr == NULL || buf == NULL || size <= 0) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
WOLFCRYPT_BIO_clear_retry_flags(bio);
wbmptr = (WOLFCRYPT_BUF_MEM *)bio->ptr;
if ((int)wbmptr->length > (size - 1))
blen = size - 1;
else if (wbmptr->length <= 0) {
*buf = '\0';
return 0;
}
else
blen = wbmptr->length;
for (i = 0; i < blen; i++) {
if (wbmptr->data[i] == '\n') {
i++;
break;
}
}
i = WOLFCRYPT_BIO_mem_read(bio, buf, i);
if (i > 0)
buf[i] = '\0';
return i;
}
static int WOLFCRYPT_BIO_mem_puts(WOLFCRYPT_BIO *bio, const char *str)
{
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
return WOLFCRYPT_BIO_mem_write(bio, str, (int)strlen(str));
}
#endif /* OPENSSL_EXTRA */

152
wolfcrypt/src/bio_m_null.c Normal file
View File

@@ -0,0 +1,152 @@
/* bio_m_null.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
static int WOLFCRYPT_BIO_null_write(WOLFCRYPT_BIO *bio,
const char *buf, int size);
static int WOLFCRYPT_BIO_null_read(WOLFCRYPT_BIO *bio, char *buf, int size);
static int WOLFCRYPT_BIO_null_puts(WOLFCRYPT_BIO *bio, const char *str);
static int WOLFCRYPT_BIO_null_gets(WOLFCRYPT_BIO *bio, char *buf, int size);
static long WOLFCRYPT_BIO_null_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_null_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_null_free(WOLFCRYPT_BIO *bio);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_null_method = {
BIO_TYPE_NULL,
"NULL",
WOLFCRYPT_BIO_null_write,
WOLFCRYPT_BIO_null_read,
WOLFCRYPT_BIO_null_puts,
WOLFCRYPT_BIO_null_gets,
WOLFCRYPT_BIO_null_ctrl,
WOLFCRYPT_BIO_null_new,
WOLFCRYPT_BIO_null_free,
NULL,
};
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_null(void)
{
return (&WOLFCRYPT_BIO_null_method);
}
static int WOLFCRYPT_BIO_null_new(WOLFCRYPT_BIO *bio)
{
if (bio == NULL)
return 0;
bio->init = 1;
bio->num = 0;
bio->ptr = NULL;
return 1;
}
static int WOLFCRYPT_BIO_null_free(WOLFCRYPT_BIO *bio)
{
return bio == NULL ? 0 : 1;
}
static int WOLFCRYPT_BIO_null_read(WOLFCRYPT_BIO *bio, char *buf, int size)
{
(void)bio;
(void)buf;
(void)size;
return 0;
}
static int WOLFCRYPT_BIO_null_write(WOLFCRYPT_BIO *bio, const char *buf, int size)
{
(void)bio;
(void)buf;
return size;
}
static long WOLFCRYPT_BIO_null_ctrl(WOLFCRYPT_BIO *bio, int cmd, long num, void *ptr)
{
(void)bio;
(void)ptr;
(void)num;
long ret = 1;
switch (cmd) {
case BIO_CTRL_RESET:
case BIO_CTRL_EOF:
case BIO_CTRL_SET:
case BIO_CTRL_SET_CLOSE:
case BIO_CTRL_FLUSH:
case BIO_CTRL_DUP:
ret = 1;
break;
case BIO_CTRL_GET_CLOSE:
case BIO_CTRL_INFO:
case BIO_CTRL_GET:
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_null_gets(WOLFCRYPT_BIO *bio, char *buf, int size)
{
(void)bio;
(void)buf;
(void)size;
return 0;
}
static int WOLFCRYPT_BIO_null_puts(WOLFCRYPT_BIO *bio, const char *str)
{
(void)bio;
if (str == NULL)
return 0;
return (int)strlen(str);
}
#endif /* OPENSSL_EXTRA */

305
wolfcrypt/src/bio_m_sock.c Normal file
View File

@@ -0,0 +1,305 @@
/* bio_m_sock.c
*
* Copyright (C) 2006-2015 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* 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-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <sys/socket.h>
#include <errno.h>
#include <wolfssl/wolfcrypt/settings.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifdef NO_INLINE
#include <wolfssl/wolfcrypt/misc.h>
#else
#include <wolfcrypt/src/misc.c>
#endif
#include <wolfssl/openssl/bio.h>
static int WOLFCRYPT_BIO_sock_write(WOLFCRYPT_BIO *bio,
const char *data, int size);
static int WOLFCRYPT_BIO_sock_read(WOLFCRYPT_BIO *bio, char *data, int size);
static int WOLFCRYPT_BIO_sock_puts(WOLFCRYPT_BIO *bio, const char *str);
static long WOLFCRYPT_BIO_sock_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long num, void *ptr);
static int WOLFCRYPT_BIO_sock_new(WOLFCRYPT_BIO *bio);
static int WOLFCRYPT_BIO_sock_free(WOLFCRYPT_BIO *bio);
static WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_sock_method = {
BIO_TYPE_SOCKET,
"Socket",
WOLFCRYPT_BIO_sock_write,
WOLFCRYPT_BIO_sock_read,
WOLFCRYPT_BIO_sock_puts,
NULL, /* gets */
WOLFCRYPT_BIO_sock_ctrl,
WOLFCRYPT_BIO_sock_new,
WOLFCRYPT_BIO_sock_free,
NULL,
};
WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_socket(void)
{
return (&WOLFCRYPT_BIO_sock_method);
}
WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_socket(int fd, int close_flag)
{
WOLFCRYPT_BIO *ret;
ret = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_socket());
if (ret == NULL) {
WOLFSSL_ERROR(MEMORY_E);
return NULL;
}
WOLFCRYPT_BIO_set_fd(ret, fd, close_flag);
return ret;
}
static int WOLFCRYPT_BIO_sock_new(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
bio->init = 0;
bio->num = 0; /* used for fd */
bio->ptr = NULL;
bio->flags = 0;
return 1;
}
static int WOLFCRYPT_BIO_sock_free(WOLFCRYPT_BIO *bio)
{
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return 0;
}
if (!bio->shutdown)
return 1;
if (bio->init) {
shutdown(bio->num, SHUT_RDWR);
#ifdef USE_WINDOWS_API
closesocket(bio->num);
#else
close(bio->num);
#endif
}
bio->init = 0;
bio->flags = 0;
return 1;
}
static int WOLFCRYPT_BIO_sock_read(WOLFCRYPT_BIO *bio, char *data, int size)
{
int ret;
if (bio == NULL || !bio->init || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
#ifdef USE_WINDOWS_API
WSASetLastError(0);
ret = (int)recv(bio->num, data, size, 0);
#else
errno = 0;
ret = (int)read(bio->num, data, size);
#endif
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (WOLFCRYPT_BIO_sock_should_retry(ret))
WOLFCRYPT_BIO_set_retry_read(bio);
}
return ret;
}
static int WOLFCRYPT_BIO_sock_write(WOLFCRYPT_BIO *bio,
const char *data, int size)
{
int ret;
if (bio == NULL || !bio->init || data == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
#ifdef USE_WINDOWS_API
WSASetLastError(0);
ret = (int)send(bio->num, data, size, 0);
#else
errno = 0;
ret = (int)write(bio->num, data, size);
#endif
WOLFCRYPT_BIO_clear_retry_flags(bio);
if (ret <= 0) {
if (WOLFCRYPT_BIO_sock_should_retry(ret))
WOLFCRYPT_BIO_set_retry_write(bio);
}
return ret;
}
static long WOLFCRYPT_BIO_sock_ctrl(WOLFCRYPT_BIO *bio,
int cmd, long num, void *ptr)
{
long ret = 1;
if (bio == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
switch (cmd) {
case BIO_C_SET_FD:
WOLFCRYPT_BIO_sock_free(bio);
bio->num = *((int *)ptr);
bio->shutdown = (int)num;
bio->init = 1;
break;
case BIO_C_GET_FD:
if (bio->init) {
if (ptr != NULL)
*((int *)ptr) = bio->num;
ret = bio->num;
}
else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = bio->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
bio->shutdown = (int)num;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
static int WOLFCRYPT_BIO_sock_puts(WOLFCRYPT_BIO *bio, const char *str)
{
if (bio == NULL || str == NULL) {
WOLFSSL_ERROR(BAD_FUNC_ARG);
return -1;
}
return WOLFCRYPT_BIO_sock_write(bio, str, (int)strlen(str));
}
int WOLCRYPT_BIO_sock_non_fatal_error(int err)
{
switch (err) {
#if defined(WSAEWOULDBLOCK)
case WSAEWOULDBLOCK:
#endif
#ifdef EWOULDBLOCK
#ifdef WSAEWOULDBLOCK
#if WSAEWOULDBLOCK != EWOULDBLOCK
case EWOULDBLOCK:
#endif
#else
case EWOULDBLOCK:
#endif
#endif
#if defined(ENOTCONN)
case ENOTCONN:
#endif
#ifdef EINTR
case EINTR:
#endif
#ifdef EAGAIN
#if EWOULDBLOCK != EAGAIN
case EAGAIN:
#endif
#endif
#ifdef EPROTO
case EPROTO:
#endif
#ifdef EINPROGRESS
case EINPROGRESS:
#endif
#ifdef EALREADY
case EALREADY:
#endif
return 1;
break;
default:
break;
}
return 0;
}
int WOLFCRYPT_BIO_sock_should_retry(int i)
{
if (!i || i == -1) {
int ret;
#ifdef USE_WINDOWS_API
ret = WSAGetLastError();
#else
ret = errno;
#endif
return WOLCRYPT_BIO_sock_non_fatal_error(ret);
}
return 0;
}
#endif /* OPENSSL_EXTRA */

View File

@@ -373,6 +373,99 @@ const char* wc_GetErrorString(int error)
case HASH_TYPE_E:
return "Hash type not enabled/available";
case BIO_CALLBACK_E:
return "BIO callback function failed";
case BIO_CREATE_METHOD_E:
return "BIO method create function failed";
case BIO_FIND_TYPE_E:
return "BIO find type failed";
case BIO_CTRL_E:
return "BIO Control function failed";
case BIO_UNINITIALIZED_E:
return "BIO is not initialized";
case BIO_PUTS_E:
return "BIO puts failed";
case BIO_FILE_READ_E:
return "BIO file read failed";
case BIO_FILE_WRITE_E:
return "BIO file write failed";
case BIO_FILE_MODE_E:
return "BIO file bad open mode";
case BIO_FILE_OPEN_E:
return "BIO file open failed";
case BIO_FILE_GETS_E:
return "BIO file gets failed";
case BIO_MEM_WRITE_E:
return "BIO memory write failed";
case BIO_B64_ENCODE_E:
return "BIO filter base64 encode failed";
case BIO_B64_DECODE_E:
return "BIO filter base64 decode failed";
case BIO_DGST_INIT_E:
return "BIO filter digest init failed";
case BIO_DGST_UPDATE_E:
return "BIO filter digest update failed";
case BIO_DGST_FINAL_E:
return "BIO filter digest final failed";
case BIO_NO_HOSTNAME_E:
return "BIO connect, no hostname provided";
case BIO_NO_PORT_E:
return "BIO connect, no port provided";
case BIO_CREATE_SOCKET_E:
return "BIO connect, create socket failed";
case BIO_NBIO_E:
return "BIO connect, NBIO error";
case BIO_CONNECT_E:
return "BIO connect, connect failed";
case BIO_ADDR_AF_INET_E:
return "BIO connect, address not AF_INET type";
case BIO_SRV_PROTO_E:
return "BIO connect, bad server protocol";
case BIO_WSASTARTUP_E:
return "BIO connect, WSA Startup failed";
case BIO_BIND_SOCKET_E:
return "BIO connect, Bind socket failed";
case BIO_LISTEN_SOCKET_E:
return "BIO connect, Listen socket failed";
case BIO_ACCEPT_E:
return "BIO connect, Accept failed";
case BIO_KEEPALIVE_E:
return "BIO connect, Keep ALive failed";
case BIO_OPTIONS_E:
return "BIO connect, Options error";
case BIO_BAD_REF:
return "BIO, Bad reference number";
default:
return "unknown error number";

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,11 @@
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/ssl.h>
#ifdef OPENSSL_EXTRA
#include <wolfssl/openssl/bio.h>
#endif
#ifdef HAVE_CRL
#include <wolfssl/crl.h>
#endif
@@ -1159,35 +1164,6 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void);
WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
#endif
enum BIO_TYPE {
BIO_BUFFER = 1,
BIO_SOCKET = 2,
BIO_SSL = 3,
BIO_MEMORY = 4
};
/* wolfSSL BIO_METHOD type */
struct WOLFSSL_BIO_METHOD {
byte type; /* method type */
};
/* wolfSSL BIO type */
struct WOLFSSL_BIO {
byte type; /* method type */
byte close; /* close flag */
byte eof; /* eof flag */
WOLFSSL* ssl; /* possible associated ssl */
byte* mem; /* memory buffer */
int memLen; /* memory buffer length */
int fd; /* possible file descriptor */
WOLFSSL_BIO* prev; /* previous in chain */
WOLFSSL_BIO* next; /* next in chain */
};
/* wolfSSL method type */
struct WOLFSSL_METHOD {
ProtocolVersion version;
@@ -2120,6 +2096,7 @@ WOLFSSL_LOCAL
WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*);
WOLFSSL_LOCAL
int SetSession(WOLFSSL*, WOLFSSL_SESSION*);
WOLFSSL_LOCAL int DupSession(WOLFSSL* ssl, WOLFSSL* ossl);
typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int);
@@ -2663,6 +2640,8 @@ void FreeSSL(WOLFSSL*);
WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */
WOLFSSL_LOCAL int DupSSL(WOLFSSL* ssl, WOLFSSL* ossl);
enum {
IV_SZ = 32, /* max iv sz */
NAME_SZ = 80 /* max one line */

View File

@@ -1,23 +1,564 @@
/* bio.h for openssl */
#ifndef WOLFCRYPT_BIO_H_
#define WOLFCRYPT_BIO_H_
#include <stdio.h>
#ifndef WOLFSSL_BIO_H_
#define WOLFSSL_BIO_H_
#include <wolfssl/openssl/ssl.h>
#include <wolfssl/wolfcrypt/types.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/openssl/evp.h>
#ifdef OPENSSL_EXTRA
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/* BIO types */
enum WS_BIO_TYPE {
BIO_TYPE_NONE = 0,
BIO_TYPE_SSL = 1,
BIO_TYPE_MD = 2, /* passive */
BIO_TYPE_BUFFER = 3,
BIO_TYPE_CIPHER = 4,
BIO_TYPE_BASE64 = 5,
BIO_TYPE_LINEBUFFER = 6,
BIO_TYPE_ASN1 = 7,
BIO_TYPE_COMP = 8,
BIO_TYPE_PROXY_CLIENT = 9, /* client proxy BIO */
BIO_TYPE_PROXY_SERVER = 10, /* server proxy BIO */
BIO_TYPE_NULL_FILTER = 11,
BIO_TYPE_BER = 12, /* BER -> bin filter */
BIO_TYPE_MEM = 13,
BIO_TYPE_FILE = 14,
BIO_TYPE_NULL = 15,
BIO_TYPE_BIO = 16, /* (half a) BIO pair */
/* socket, fd, connect or accept */
BIO_TYPE_DESCRIPTOR = 0x100,
BIO_TYPE_FD = 17|BIO_TYPE_DESCRIPTOR,
BIO_TYPE_SOCKET = 18|BIO_TYPE_DESCRIPTOR,
/* socket - connect */
BIO_TYPE_CONNECT = 19|BIO_TYPE_DESCRIPTOR,
/* socket for accept */
BIO_TYPE_ACCEPT = 20|BIO_TYPE_DESCRIPTOR,
BIO_TYPE_DGRAM = 21|BIO_TYPE_DESCRIPTOR,
};
/*
* BIO_FILENAME_READ|BIO_CLOSE to open or close on free.
* BIO_set_fp(in,stdin,BIO_NOCLOSE);
*/
#if !defined(BIO_CLOSE) || !defined(BIO_NOCLOSE)
#define BIO_CLOSE 1
#define BIO_NOCLOSE 0
#endif
/*enum WS_BIO_FILE {
BIO_NOCLOSE = 0,
BIO_CLOSE = 1,
};*/
/*
* These are used in the following macros and are passed to BIO_ctrl()
*/
enum WS_BIO_CTRL {
BIO_CTRL_RESET = 1, /* opt - rewind/zero etc */
BIO_CTRL_EOF = 2, /* opt - are we at the eof */
BIO_CTRL_INFO = 3, /* opt - extra tit-bits */
BIO_CTRL_SET = 4, /* man - set the 'IO' type */
BIO_CTRL_GET = 5, /* man - get the 'IO' type */
BIO_CTRL_PUSH = 6, /* opt - internal, used to signify change */
BIO_CTRL_POP = 7, /* opt - internal, used to signify change */
BIO_CTRL_GET_CLOSE = 8, /* man - set the 'close' on free */
BIO_CTRL_SET_CLOSE = 9, /* man - set the 'close' on free */
BIO_CTRL_PENDING = 10, /* opt - is their more data buffered */
BIO_CTRL_FLUSH = 11, /* opt - 'flush' buffered output */
BIO_CTRL_DUP = 12, /* man - extra stuff for 'duped' BIO */
BIO_CTRL_WPENDING = 13, /* opt - number of bytes still to write */
/* callback is int cb(BIO *bio,state,ret); */
BIO_CTRL_SET_CALLBACK = 14, /* opt - set callback function */
BIO_CTRL_GET_CALLBACK = 15, /* opt - set callback function */
BIO_CTRL_SET_FILENAME = 30, /* BIO_s_file special */
/* dgram BIO stuff */
BIO_CTRL_DGRAM_CONNECT = 31, /* BIO dgram special */
BIO_CTRL_DGRAM_SET_CONNECTED = 32, /* allow for an externally connected
* socket to be passed in */
BIO_CTRL_DGRAM_SET_RECV_TIMEOUT = 33, /* setsockopt, essentially */
BIO_CTRL_DGRAM_GET_RECV_TIMEOUT = 34, /* getsockopt, essentially */
BIO_CTRL_DGRAM_SET_SEND_TIMEOUT = 35, /* setsockopt, essentially */
BIO_CTRL_DGRAM_GET_SEND_TIMEOUT = 36, /* getsockopt, essentially */
BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP = 37, /* flag whether the last */
BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP = 38, /* I/O operation tiemd out */
/* #ifdef IP_MTU_DISCOVER */
BIO_CTRL_DGRAM_MTU_DISCOVER = 39, /* set DF bit on egress packets */
/* #endif */
BIO_CTRL_DGRAM_QUERY_MTU = 40, /* as kernel for current MTU */
BIO_CTRL_DGRAM_GET_FALLBACK_MTU = 47,
BIO_CTRL_DGRAM_GET_MTU = 41, /* get cached value for MTU */
BIO_CTRL_DGRAM_SET_MTU = 42, /* set cached value for MTU.
* want to use this if asking
* the kernel fails */
BIO_CTRL_DGRAM_MTU_EXCEEDED = 43, /* check whether the MTU was
* exceed in the previous write
* operation */
BIO_CTRL_DGRAM_GET_PEER = 46,
BIO_CTRL_DGRAM_SET_PEER = 44, /* Destination for the data */
BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT = 45, /* Next DTLS handshake timeout
* to adjust socket timeouts */
BIO_CTRL_DGRAM_SET_DONT_FRAG = 48,
BIO_CTRL_DGRAM_GET_MTU_OVERHEAD = 49,
};
/* modifiers */
enum WS_BIO_MOD {
BIO_FP_READ = 0x02,
BIO_FP_WRITE = 0x04,
BIO_FP_APPEND = 0x08,
BIO_FP_TEXT = 0x10,
};
/* flags */
enum WS_BIO_FLAGS {
BIO_FLAGS_READ = 0x01,
BIO_FLAGS_WRITE = 0x02,
BIO_FLAGS_IO_SPECIAL = 0x04,
BIO_FLAGS_RWS = BIO_FLAGS_READ|
BIO_FLAGS_WRITE|BIO_FLAGS_IO_SPECIAL,
BIO_FLAGS_SHOULD_RETRY = 0x08,
BIO_FLAGS_BASE64_NO_NL = 0x100,
/* Used with memory BIOs: shouldn't free up or change the data in any way.
*/
BIO_FLAGS_MEM_RDONLY = 0x200,
};
enum WS_BIO_RR {
/* Returned from the SSL bio when the certificate retrieval code had an error */
BIO_RR_SSL_X509_LOOKUP = 0x01,
/* Returned from the connect BIO when a connect would have blocked */
BIO_RR_CONNECT = 0x02,
/* Returned from the accept BIO when an accept would have blocked */
BIO_RR_ACCEPT = 0x03,
};
/* These are passed by the BIO callback */
enum WS_BIO_CB_FLAGS {
BIO_CB_FREE = 0x01,
BIO_CB_READ = 0x02,
BIO_CB_WRITE = 0x03,
BIO_CB_PUTS = 0x04,
BIO_CB_GETS = 0x05,
BIO_CB_CTRL = 0x06,
BIO_CB_RETURN = 0x80,
};
#define BIO_CB_return(a) ((a) | BIO_CB_RETURN)
#define BIO_cb_post(a) ((a) & BIO_CB_RETURN)
#define BIO_cb_pre(a) (!BIO_cb_post((a)))
typedef struct WOLFCRYPT_BIO WOLFCRYPT_BIO;
typedef struct WOLFCRYPT_BIO_METHOD WOLFCRYPT_BIO_METHOD;
typedef void WOLFCRYPT_BIO_info_cb (WOLFCRYPT_BIO *, int, const char *,
int, long, long);
/* wolfSSL BIO_METHOD type */
struct WOLFCRYPT_BIO_METHOD {
int type; /* method type */
const char *name;
int (*bwrite) (WOLFCRYPT_BIO *, const char *, int);
int (*bread) (WOLFCRYPT_BIO *, char *, int);
int (*bputs) (WOLFCRYPT_BIO *, const char *);
int (*bgets) (WOLFCRYPT_BIO *, char *, int);
long (*ctrl) (WOLFCRYPT_BIO *, int, long, void *);
int (*create) (WOLFCRYPT_BIO *);
int (*destroy) (WOLFCRYPT_BIO *);
long (*callback_ctrl) (WOLFCRYPT_BIO *, int, WOLFCRYPT_BIO_info_cb *);
};
struct WOLFCRYPT_BIO {
WOLFCRYPT_BIO_METHOD *method;
/* bio, mode, argp, argi, argl, ret */
long (*callback) (WOLFCRYPT_BIO *, int, const char *, int, long, long);
char *cb_arg; /* first argument for the callback */
int init;
int shutdown;
int flags; /* extra storage */
int retry_reason;
int num;
void *ptr;
WOLFCRYPT_BIO *next_bio; /* used by filter BIOs */
WOLFCRYPT_BIO *prev_bio; /* used by filter BIOs */
int references;
wolfSSL_Mutex refMutex; /* to lock r/w on references */
unsigned long num_read;
unsigned long num_write;
};
enum WS_BIO_C_FLAGS {
BIO_C_SET_CONNECT = 100,
BIO_C_DO_STATE_MACHINE = 101,
BIO_C_SET_NBIO = 102,
BIO_C_SET_PROXY_PARAM = 103,
BIO_C_SET_FD = 104,
BIO_C_GET_FD = 105,
BIO_C_SET_FILE_PTR = 106,
BIO_C_GET_FILE_PTR = 107,
BIO_C_SET_FILENAME = 108,
BIO_C_SET_SSL = 109,
BIO_C_GET_SSL = 110,
BIO_C_SET_MD = 111,
BIO_C_GET_MD = 112,
BIO_C_GET_CIPHER_STATUS = 113,
BIO_C_SET_BUF_MEM = 114,
BIO_C_GET_BUF_MEM_PTR = 115,
BIO_C_GET_BUFF_NUM_LINES = 116,
BIO_C_SET_BUFF_SIZE = 117,
BIO_C_SET_ACCEPT = 118,
BIO_C_SSL_MODE = 119,
BIO_C_GET_MD_CTX = 120,
BIO_C_GET_PROXY_PARAM = 121,
BIO_C_SET_BUFF_READ_DATA = 122, /* data to read first */
BIO_C_GET_CONNECT = 123,
BIO_C_GET_ACCEPT = 124,
BIO_C_SET_SSL_RENEGOTIATE_BYTES = 125,
BIO_C_GET_SSL_NUM_RENEGOTIATES = 126,
BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT = 127,
BIO_C_FILE_SEEK = 128,
BIO_C_GET_CIPHER_CTX = 129,
BIO_C_SET_BUF_MEM_EOF_RETURN = 130, /* return end of input
* value */
BIO_C_SET_BIND_MODE = 131,
BIO_C_GET_BIND_MODE = 132,
BIO_C_FILE_TELL = 133,
BIO_C_GET_SOCKS = 134,
BIO_C_SET_SOCKS = 135,
BIO_C_SET_WRITE_BUF_SIZE = 136, /* for BIO_s_bio */
BIO_C_GET_WRITE_BUF_SIZE = 137,
BIO_C_MAKE_BIO_PAIR = 138,
BIO_C_DESTROY_BIO_PAIR = 139,
BIO_C_GET_WRITE_GUARANTEE = 140,
BIO_C_GET_READ_REQUEST = 141,
BIO_C_SHUTDOWN_WR = 142,
BIO_C_NREAD0 = 143,
BIO_C_NREAD = 144,
BIO_C_NWRITE0 = 145,
BIO_C_NWRITE = 146,
BIO_C_RESET_READ_REQUEST = 147,
BIO_C_SET_MD_CTX = 148,
BIO_C_SET_PREFIX = 149,
BIO_C_GET_PREFIX = 150,
BIO_C_SET_SUFFIX = 151,
BIO_C_GET_SUFFIX = 152,
BIO_C_SET_EX_ARG = 153,
BIO_C_GET_EX_ARG = 154,
};
/* connect BIO */
enum WS_BIO_CONN {
BIO_CONN_S_BEFORE = 1,
BIO_CONN_S_GET_IP = 2,
BIO_CONN_S_GET_PORT = 3,
BIO_CONN_S_CREATE_SOCKET = 4,
BIO_CONN_S_CONNECT = 5,
BIO_CONN_S_OK = 6,
BIO_CONN_S_BLOCKED_CONNECT = 7,
BIO_CONN_S_NBIO = 8,
};
enum WS_BIO_BIND {
BIO_BIND_NORMAL = 0,
BIO_BIND_REUSEADDR_IF_UNUSED = 1,
BIO_BIND_REUSEADDR = 2,
};
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_METHOD *method);
WOLFSSL_API int WOLFCRYPT_BIO_free(WOLFCRYPT_BIO *bio);
WOLFSSL_API void WOLFCRYPT_BIO_free_all(WOLFCRYPT_BIO *bio);
WOLFSSL_API const char *WOLFCRYPT_BIO_method_name(const WOLFCRYPT_BIO *bio);
WOLFSSL_API int WOLFCRYPT_BIO_method_type(const WOLFCRYPT_BIO *bio);
WOLFSSL_API int WOLFCRYPT_BIO_set(WOLFCRYPT_BIO *bio,
WOLFCRYPT_BIO_METHOD *method);
WOLFSSL_API void WOLFCRYPT_BIO_clear_flags(WOLFCRYPT_BIO *bio, int flags);
WOLFSSL_API void WOLFCRYPT_BIO_set_flags(WOLFCRYPT_BIO *bio, int flags);
WOLFSSL_API int WOLFCRYPT_BIO_test_flags(const WOLFCRYPT_BIO *bio, int flags);
#define WOLFCRYPT_BIO_get_flags(b) WOLFCRYPT_BIO_test_flags(b, ~(0x0))
#define WOLFCRYPT_BIO_set_retry_special(b) \
WOLFCRYPT_BIO_set_flags(b, (BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY))
#define WOLFCRYPT_BIO_set_retry_read(b) \
WOLFCRYPT_BIO_set_flags(b, (BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY))
#define WOLFCRYPT_BIO_set_retry_write(b) \
WOLFCRYPT_BIO_set_flags(b, (BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY))
#define WOLFCRYPT_BIO_clear_retry_flags(b) \
WOLFCRYPT_BIO_clear_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
#define WOLFCRYPT_BIO_get_retry_flags(b) \
WOLFCRYPT_BIO_test_flags(b, (BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY))
/* These should be used by the application to tell why we should retry */
#define WOLFCRYPT_BIO_should_read(f) \
WOLFCRYPT_BIO_test_flags(f, BIO_FLAGS_READ)
#define WOLFCRYPT_BIO_should_write(f) \
WOLFCRYPT_BIO_test_flags(f, BIO_FLAGS_WRITE)
#define WOLFCRYPT_BIO_should_io_special(f) \
WOLFCRYPT_BIO_test_flags(f, BIO_FLAGS_IO_SPECIAL)
#define WOLFCRYPT_BIO_retry_type(f) \
WOLFCRYPT_BIO_test_flags(f, BIO_FLAGS_RWS)
#define WOLFCRYPT_BIO_should_retry(f) \
WOLFCRYPT_BIO_test_flags(f, BIO_FLAGS_SHOULD_RETRY)
WOLFSSL_API long (*WOLFCRYPT_BIO_get_callback(const WOLFCRYPT_BIO *bio))
(WOLFCRYPT_BIO *, int, const char *, int, long, long);
WOLFSSL_API void WOLFCRYPT_BIO_set_callback(WOLFCRYPT_BIO *bio,
long (*cb) (WOLFCRYPT_BIO *, int,
const char *, int, long, long));
WOLFSSL_API void WOLFCRYPT_BIO_set_callback_arg(WOLFCRYPT_BIO *bio, char *arg);
WOLFSSL_API char *WOLFCRYPT_BIO_get_callback_arg(const WOLFCRYPT_BIO *bio);
WOLFSSL_API int WOLFCRYPT_BIO_read(WOLFCRYPT_BIO *bio, void *out, int outl);
WOLFSSL_API int WOLFCRYPT_BIO_write(WOLFCRYPT_BIO *bio, const void *in, int inl);
WOLFSSL_API int WOLFCRYPT_BIO_puts(WOLFCRYPT_BIO *bio, const char *in);
WOLFSSL_API int WOLFCRYPT_BIO_gets(WOLFCRYPT_BIO *bio, char *in, int inl);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_push(WOLFCRYPT_BIO *top,
WOLFCRYPT_BIO *next);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_pop(WOLFCRYPT_BIO *bio);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_next(WOLFCRYPT_BIO *bio);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_get_retry_BIO(WOLFCRYPT_BIO *bio,
int *reason);
WOLFSSL_API int WOLFCRYPT_BIO_get_retry_reason(WOLFCRYPT_BIO *bio);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_find_type(WOLFCRYPT_BIO *bio, int type);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_dup_chain(WOLFCRYPT_BIO *bio);
#define WOLFCRYPT_BIO_dup_state(bio, ret) \
WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_DUP, 0, ret)
WOLFSSL_API long WOLFCRYPT_BIO_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long larg, void *parg);
WOLFSSL_API long WOLFCRYPT_BIO_callback_ctrl(WOLFCRYPT_BIO *bio, int cmd,
void (*fp) (WOLFCRYPT_BIO *, int,
const char *, int, long, long));
WOLFSSL_API long WOLFCRYPT_BIO_int_ctrl(WOLFCRYPT_BIO *bio, int cmd,
long larg, int iarg);
WOLFSSL_API char *WOLFCRYPT_BIO_ptr_ctrl(WOLFCRYPT_BIO *bio, int cmd, long larg);
WOLFSSL_API size_t WOLFCRYPT_BIO_ctrl_pending(WOLFCRYPT_BIO *bio);
WOLFSSL_API size_t WOLFCRYPT_BIO_ctrl_wpending(WOLFCRYPT_BIO *bio);
WOLFSSL_API int WOLFCRYPT_BIO_indent(WOLFCRYPT_BIO *bio, int indent, int max);
WOLFSSL_API unsigned long WOLFCRYPT_BIO_number_read(WOLFCRYPT_BIO *bio);
WOLFSSL_API unsigned long WOLFCRYPT_BIO_number_written(WOLFCRYPT_BIO *bio);
#define WOLFCRYPT_BIO_reset(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL)
#define WOLFCRYPT_BIO_eof(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL)
#define WOLFCRYPT_BIO_set_close(bio,c) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, (c), NULL)
#define WOLFCRYPT_BIO_get_close(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_GET_CLOSE, 0, NULL)
#define WOLFCRYPT_BIO_pending(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL)
#define WOLFCRYPT_BIO_wpending(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL)
#define WOLFCRYPT_BIO_flush(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, NULL)
#define WOLFCRYPT_BIO_set_info_callback(bio, cb) \
(int)WOLFCRYPT_BIO_callback_ctrl(bio, BIO_CTRL_SET_CALLBACK, cb)
#define WOLFCRYPT_BIO_get_info_callback(bio, cb) \
(int)WOLFCRYPT_BIO_callback_ctrl(bio, BIO_CTRL_GET_CALLBACK, 0, cb)
WOLFSSL_API void WOLFCRYPT_BIO_copy_next_retry(WOLFCRYPT_BIO *b);
WOLFSSL_API int WOLFCRYPT_BIO_printf(WOLFCRYPT_BIO *bio,
const char *format, ...);
/* BIO file */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_file(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_fp(XFILE f, int close_flag);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_file(const char *name,
const char *mode);
#define WOLFCRYPT_BIO_set_fp(bio, f, c) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_FILE_PTR, c, (char *)f)
#define WOLFCRYPT_BIO_get_fp(bio, f) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_FILE_PTR, 0, (char *)f)
#define WOLFCRYPT_BIO_seek(bio, ofs) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_C_FILE_SEEK, ofs, NULL)
#define WOLFCRYPT_BIO_tell(bio) \
(int)WOLFCRYPT_BIO_ctrl(bio, BIO_C_FILE_TELL, 0, NULL)
#define WOLFCRYPT_BIO_read_filename(bio, name) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE|BIO_FP_READ, name)
#define WOLFCRYPT_BIO_write_filename(bio, name) \
WOLFCRYPT_BIO_ctrl(bio,BIO_C_SET_FILENAME, BIO_CLOSE|BIO_FP_WRITE, name)
#define WOLFCRYPT_BIO_append_filename(bio, name) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_FILENAME, BIO_CLOSE|BIO_FP_APPEND, name)
#define WOLFCRYPT_BIO_rw_filename(bio, name) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_FILENAME, \
BIO_CLOSE|BIO_FP_READ|BIO_FP_WRITE,name)
/* BIO memory */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_mem(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_mem_buf(void *data, int len);
/* BIO fd */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_fd(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_fd(int fd, int close_flag);
/* BIO null */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_null(void);
/* BIO socket */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_socket(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_socket(int fd, int close_flag);
WOLFSSL_API int WOLFCRYPT_BIO_sock_should_retry(int i);
WOLFSSL_API int WOLCRYPT_BIO_sock_non_fatal_error(int err);
#define WOLFCRYPT_BIO_set_fd(bio, fd, c) \
WOLFCRYPT_BIO_int_ctrl(bio, BIO_C_SET_FD, c, fd)
#define WOLFCRYPT_BIO_get_fd(bio, c) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_FD, 0, (char *)c)
/* BIO connect */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_connect(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_connect(const char *host_port);
#define WOLFCRYPT_BIO_set_conn_hostname(bio, hname) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_CONNECT, 0, (char *)hname)
#define WOLFCRYPT_BIO_set_conn_port(bio, port) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (char *)port)
#define WOLFCRYPT_BIO_set_conn_ip(bio, ip) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_CONNECT, 2, (char *)ip)
#define WOLFCRYPT_BIO_set_conn_int_port(bio, port) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_CONNECT, 3, (char *)port)
#define WOLFCRYPT_BIO_get_conn_hostname(bio) \
WOLFCRYPT_BIO_ptr_ctrl(bio, BIO_C_GET_CONNECT, 0)
#define WOLFCRYPT_BIO_get_conn_port(bio) \
WOLFCRYPT_BIO_ptr_ctrl(bio, BIO_C_GET_CONNECT, 1)
#define WOLFCRYPT_BIO_get_conn_ip(bio) \
WOLFCRYPT_BIO_ptr_ctrl(bio, BIO_C_GET_CONNECT, 2)
#define WOLFCRYPT_BIO_get_conn_int_port(bio) \
WOLFCRYPT_BIO_int_ctrl(bio, BIO_C_GET_CONNECT, 3, 0)
#define WOLFCRYPT_BIO_set_nbio(bio, n) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_NBIO, n, NULL)
#define WOLFCRYPT_BIO_do_handshake(bio) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL)
#define WOLFCRYPT_BIO_do_connect(bio) WOLFCRYPT_BIO_do_handshake(bio)
#define WOLFCRYPT_BIO_do_accept(bio) WOLFCRYPT_BIO_do_handshake(bio)
/* BIO accept */
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_accept(const char *str);
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_accept(void);
#define WOLFCRYPT_BIO_set_accept_port(bio, name) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_ACCEPT, 0, (char *)name)
#define WOLFCRYPT_BIO_set_accept_bios(bio, nbio) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_ACCEPT, 2, nbio)
#define WOLFCRYPT_BIO_set_bind_mode(bio, mode) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_BIND_MODE, mode, NULL)
#define WOLFCRYPT_BIO_set_socket_options(bio, opt) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_EX_ARG, opt, NULL)
/* BIO datagram */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_s_datagram(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_dgram(int fd, int close_flag);
/* BIO filter buffer */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_buffer(void);
#define WOLFCRYPT_BIO_get_mem_data(bio, data) \
WOLFCRYPT_BIO_ctrl(bio, BIO_CTRL_INFO, 0, data)
#define WOLFCRYPT_BIO_set_mem_buf(bio, data, c) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_BUF_MEM, c, data)
#define WOLFCRYPT_BIO_get_mem_ptr(b, ptr) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR,0, (char *)ptr)
#define WOLFCRYPT_BIO_set_mem_eof_return(bio, v) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, v, NULL)
#define WOLFCRYPT_BIO_get_buffer_num_lines(bio) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_BUFF_NUM_LINES, 0, NULL)
#define WOLFCRYPT_BIO_set_buffer_size(bio, size) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_BUFF_SIZE, size, NULL)
#define WOLFCRYPT_BIO_set_read_buffer_size(bio, size) \
WOLFCRYPT_BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, size, 0)
#define WOLFCRYPT_BIO_set_write_buffer_size(bio, size) \
WOLFCRYPT_BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, size, 1)
#define WOLFCRYPT_BIO_set_buffer_read_data(bio, buf, num) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_BUFF_READ_DATA, num, buf)
/* BIO filter cipher */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_cipher(void);
WOLFSSL_API void WOLFCRYPT_BIO_set_cipher(WOLFCRYPT_BIO *bio,
const WOLFSSL_EVP_CIPHER *cipher,
const unsigned char *key,
const unsigned char *iv, int enc);
#define WOLFCRYPT_BIO_get_cipher_status(bio) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_CIPHER_STATUS, 0, NULL)
#define WOLFCRYPT_BIO_get_cipher_ctx(bio, ctx) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_CIPHER_CTX, 0, ctx)
/* BIO filter base64 */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_base64(void);
/* BIO filter digest */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_md(void);
#define WOLFCRYPT_BIO_set_md(bio, md) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_MD, 0, (WOLFSSL_EVP_MD *)md)
#define WOLFCRYPT_BIO_get_md(bio,md) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_MD, 0, (WOLFSSL_EVP_MD *)md)
#define WOLFCRYPT_BIO_get_md_ctx(bio,ctx) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_MD_CTX, 0, (WOLFSSL_EVP_MD_CTX *)ctx)
#define WOLFCRYPT_BIO_set_md_ctx(bio, ctx) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_MD_CTX, 0, (WOLFSSL_EVP_MD_CTX *)ctx)
/* BIO filter SSL */
WOLFSSL_API WOLFCRYPT_BIO_METHOD *WOLFCRYPT_BIO_f_ssl(void);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_buffer_ssl_connect(WOLFSSL_CTX *ctx);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_ssl_connect(WOLFSSL_CTX *ctx);
WOLFSSL_API WOLFCRYPT_BIO *WOLFCRYPT_BIO_new_ssl(WOLFSSL_CTX *ctx, int client);
WOLFSSL_API void WOLFCRYPT_BIO_ssl_shutdown(WOLFCRYPT_BIO *bio);
#define WOLFCRYPT_BIO_set_ssl(bio, ssl, mode) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_SET_SSL, mode, ssl)
#define WOLFCRYPT_BIO_get_ssl(bio, ssl) \
WOLFCRYPT_BIO_ctrl(bio, BIO_C_GET_SSL, 0, ssl)
/* BIO socket internal functions */
int WOLFCRYPT_BIO_get_host_ip(const char *str, unsigned char *ip);
int WOLFCRYPT_BIO_get_port(const char *str, unsigned short *port_ptr);
int WOLFCRYPT_BIO_sock_error(int sock);
int WOLFCRYPT_BIO_sock_init(void);
void WOLFCRYPT_BIO_sock_cleanup(void);
int WOLFCRYPT_BIO_get_accept_socket(char *host, int bind_mode);
int WOLFCRYPT_BIO_accept(int sock, char **addr);
int WOLFCRYPT_BIO_set_tcp_ndelay(int s, int on);
int WOLFCRYPT_BIO_set_tcp_nsigpipe(int s, int on);
int WOLFCRYPT_BIO_socket_nbio(int s, int mode);
#ifdef __cplusplus
} /* extern "C" */
} /* extern "C" */
#endif
#endif /* WOLFSSL_BIO_H_ */
#endif /* OPENSSL_EXTRA */
#endif /* WOLFCRYPT_BIO_H_ */

View File

@@ -46,7 +46,7 @@
#include <wolfssl/wolfcrypt/aes.h>
#include <wolfssl/wolfcrypt/des3.h>
#include <wolfssl/wolfcrypt/arc4.h>
#include <wolfssl/wolfcrypt/idea.h>
#ifdef __cplusplus
extern "C" {
@@ -97,6 +97,8 @@ typedef union {
typedef struct WOLFSSL_EVP_MD_CTX {
unsigned char macType;
int macSize;
const WOLFSSL_EVP_MD *digest;
WOLFSSL_Hasher hash;
} WOLFSSL_EVP_MD_CTX;
@@ -139,12 +141,22 @@ enum {
typedef struct WOLFSSL_EVP_CIPHER_CTX {
int keyLen; /* user may set for variable */
int blockSize;
int bufLen;
unsigned char enc; /* if encrypt side, then true */
unsigned char cipherType;
unsigned char final_used;
unsigned char ivUpdate;
unsigned char padding;
#ifndef NO_AES
unsigned char iv[AES_BLOCK_SIZE]; /* working iv pointer into cipher */
unsigned char buf[AES_BLOCK_SIZE];
unsigned char final[AES_BLOCK_SIZE];
#elif !defined(NO_DES3)
unsigned char iv[DES_BLOCK_SIZE]; /* working iv pointer into cipher */
unsigned char buf[DES_BLOCK_SIZE];
unsigned char final[DES_BLOCK_SIZE];
#endif
WOLFSSL_Cipher cipher;
} WOLFSSL_EVP_CIPHER_CTX;
@@ -153,6 +165,8 @@ typedef struct WOLFSSL_EVP_CIPHER_CTX {
WOLFSSL_API int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md);
WOLFSSL_API void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx);
WOLFSSL_API int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx);
WOLFSSL_API int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out,
const WOLFSSL_EVP_MD_CTX *in);
WOLFSSL_API int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx,
const WOLFSSL_EVP_MD* type);
@@ -179,6 +193,12 @@ WOLFSSL_API int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx,
const WOLFSSL_EVP_CIPHER* type,
unsigned char* key, unsigned char* iv,
int enc);
WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx,
unsigned char *dst, int *dstLen,
const unsigned char *src, int len);
WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx,
unsigned char *dst, int *dstLen);
WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx);
WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx,
int keylen);
@@ -186,6 +206,9 @@ WOLFSSL_API int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx,
unsigned char* dst, unsigned char* src,
unsigned int len);
WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_copy(WOLFSSL_EVP_CIPHER_CTX *out,
const WOLFSSL_EVP_CIPHER_CTX *in);
WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int);
WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY*);

View File

@@ -92,8 +92,8 @@ typedef struct WOLFSSL_CIPHER WOLFSSL_CIPHER;
typedef struct WOLFSSL_X509_LOOKUP WOLFSSL_X509_LOOKUP;
typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD;
typedef struct WOLFSSL_X509_CRL WOLFSSL_X509_CRL;
typedef struct WOLFSSL_BIO WOLFSSL_BIO;
typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD;
typedef struct WOLFCRYPT_BIO WOLFSSL_BIO;
typedef struct WOLFCRYPT_BIO_METHOD WOLFSSL_BIO_METHOD;
typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION;
typedef struct WOLFSSL_ASN1_TIME WOLFSSL_ASN1_TIME;
typedef struct WOLFSSL_ASN1_INTEGER WOLFSSL_ASN1_INTEGER;
@@ -259,6 +259,7 @@ WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int);
WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*);
WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*);
WOLFSSL_API WOLFSSL* wolfSSL_dup(WOLFSSL*);
WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int);
WOLFSSL_API char* wolfSSL_get_cipher_list(int priority);
WOLFSSL_API int wolfSSL_get_ciphers(char*, int);
@@ -394,7 +395,7 @@ WOLFSSL_API void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX*);
WOLFSSL_API void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX*, const void*, unsigned long);
WOLFSSL_API void wolfSSL_MD4_Final(unsigned char*, WOLFSSL_MD4_CTX*);
/*
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*);
WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*);
WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*);
@@ -420,7 +421,7 @@ WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len);
WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag);
WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr);
*/
WOLFSSL_API int wolfSSL_add_all_algorithms(void);
@@ -633,10 +634,6 @@ enum {
SSL_MODE_ENABLE_PARTIAL_WRITE = 2,
BIO_FLAGS_BASE64_NO_NL = 1,
BIO_CLOSE = 1,
BIO_NOCLOSE = 0,
NID_undef = 0,
X509_FILETYPE_PEM = 8,
@@ -802,7 +799,6 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_want_read(WOLFSSL*);
WOLFSSL_API int wolfSSL_want_write(WOLFSSL*);
WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...);
WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*,
const WOLFSSL_ASN1_UTCTIME*);
WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_X509_REVOKED*);
@@ -1629,8 +1625,6 @@ typedef struct WOLFSSL_X509_NAME_ENTRY {
WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name);
WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x);
WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey);
WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name);
WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void);
/* These are to be merged shortly */
WOLFSSL_API const char * wolf_OBJ_nid2sn(int n);
WOLFSSL_API int wolf_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
@@ -1654,7 +1648,6 @@ WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( STACK_OF(WOLFSSL_X
WOLFSSL_API char * wolf_OBJ_nid2ln(int n);
WOLFSSL_API int wolf_OBJ_txt2nid(const char *sn);
WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode);
WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*);
WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp,
WOLFSSL_DH **x, pem_password_cb *cb, void *u);

View File

@@ -167,7 +167,39 @@ enum {
SIG_TYPE_E = -231, /* Signature Type not enabled/available */
HASH_TYPE_E = -232, /* Hash Type not enabled/available */
MIN_CODE_E = -300 /* errors -101 - -299 */
BIO_CALLBACK_E = -250, /* BIO callback function failed */
BIO_CREATE_METHOD_E = -251, /* BIO method create function failed */
BIO_FIND_TYPE_E = -252, /* BIO find type failed */
BIO_CTRL_E = -253, /* BIO Control function failed */
BIO_UNINITIALIZED_E = -254, /* BIO is not initialized */
BIO_PUTS_E = -255, /* BIO puts function failed */
BIO_FILE_READ_E = -256, /* BIO file read failed */
BIO_FILE_WRITE_E = -257, /* BIO file write failed */
BIO_FILE_MODE_E = -258, /* BIO file bad open mode */
BIO_FILE_OPEN_E = -259, /* BIO file open failed */
BIO_FILE_GETS_E = -260, /* BIO file gets failed */
BIO_MEM_WRITE_E = -261, /* BIO memory write failed */
BIO_B64_ENCODE_E = -262, /* BIO filter base64 encode failed */
BIO_B64_DECODE_E = -263, /* BIO filter base64 decode failed */
BIO_DGST_INIT_E = -264, /* BIO filter digest init failed */
BIO_DGST_UPDATE_E = -265, /* BIO filter digest update failed */
BIO_DGST_FINAL_E = -266, /* BIO filter digest final failed */
BIO_NO_HOSTNAME_E = -267, /* BIO connect, no hostname provided */
BIO_NO_PORT_E = -268, /* BIO connect, no port provided */
BIO_CREATE_SOCKET_E = -269, /* BIO connect, create socket failed */
BIO_NBIO_E = -270, /* BIO connect, NBIO error */
BIO_CONNECT_E = -271, /* BIO connect, connect failed */
BIO_ADDR_AF_INET_E = -272, /* BIO connect, address not AF_INET type */
BIO_SRV_PROTO_E = -273, /* BIO connect, bad server protocol */
BIO_WSASTARTUP_E = -274, /* BIO connect, WSA Startup failed */
BIO_BIND_SOCKET_E = -275, /* BIO connect, Bind socket failed */
BIO_LISTEN_SOCKET_E = -276, /* BIO connect, Listen socket failed */
BIO_ACCEPT_E = -277, /* BIO connect, Accept failed */
BIO_KEEPALIVE_E = -278, /* BIO connect, Keep ALive failed */
BIO_OPTIONS_E = -279, /* BIO connect, Options error */
BIO_BAD_REF = -280, /* BIO, Bad reference number */
MIN_CODE_E = -300 /* errors -101 - -299 */
/* add new companion error id strings for any new error codes
wolfcrypt/src/error.c !!! */

View File

@@ -212,8 +212,10 @@
#define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n))
#ifndef USE_WINDOWS_API
#define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#define XSNPRINTF snprintf
#else
#define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#define XSNPRINTF _snprintf
#endif
#if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN)