From 1bd65cc8a911fb56b79eedbcfe01cdd6eec1f051 Mon Sep 17 00:00:00 2001 From: Ludovic FLAMENT Date: Fri, 29 Apr 2016 16:34:11 +0200 Subject: [PATCH] First version for OpenSSL BIO compatibility --- src/include.am | 17 +- src/internal.c | 544 +++++++++++++- src/ssl.c | 846 +++++++++++++--------- wolfcrypt/src/bio.c | 823 +++++++++++++++++++++ wolfcrypt/src/bio_f_b64.c | 669 ++++++++++++++++++ wolfcrypt/src/bio_f_buff.c | 583 +++++++++++++++ wolfcrypt/src/bio_f_cipher.c | 456 ++++++++++++ wolfcrypt/src/bio_f_dgst.c | 311 ++++++++ wolfcrypt/src/bio_f_sock.c | 484 +++++++++++++ wolfcrypt/src/bio_f_ssl.c | 725 +++++++++++++++++++ wolfcrypt/src/bio_m_accept.c | 554 +++++++++++++++ wolfcrypt/src/bio_m_conn.c | 715 +++++++++++++++++++ wolfcrypt/src/bio_m_dgram.c | 795 +++++++++++++++++++++ wolfcrypt/src/bio_m_fd.c | 145 ++++ wolfcrypt/src/bio_m_file.c | 357 ++++++++++ wolfcrypt/src/bio_m_mem.c | 423 +++++++++++ wolfcrypt/src/bio_m_null.c | 152 ++++ wolfcrypt/src/bio_m_sock.c | 305 ++++++++ wolfcrypt/src/error.c | 93 +++ wolfcrypt/test/test.c | 1180 +++++++++++++++++++++++++++++++ wolfssl/internal.h | 37 +- wolfssl/openssl/bio.h | 561 ++++++++++++++- wolfssl/openssl/evp.h | 25 +- wolfssl/ssl.h | 17 +- wolfssl/wolfcrypt/error-crypt.h | 34 +- wolfssl/wolfcrypt/types.h | 2 + 26 files changed, 10442 insertions(+), 411 deletions(-) create mode 100644 wolfcrypt/src/bio.c create mode 100644 wolfcrypt/src/bio_f_b64.c create mode 100644 wolfcrypt/src/bio_f_buff.c create mode 100644 wolfcrypt/src/bio_f_cipher.c create mode 100644 wolfcrypt/src/bio_f_dgst.c create mode 100644 wolfcrypt/src/bio_f_sock.c create mode 100644 wolfcrypt/src/bio_f_ssl.c create mode 100644 wolfcrypt/src/bio_m_accept.c create mode 100644 wolfcrypt/src/bio_m_conn.c create mode 100644 wolfcrypt/src/bio_m_dgram.c create mode 100644 wolfcrypt/src/bio_m_fd.c create mode 100644 wolfcrypt/src/bio_m_file.c create mode 100644 wolfcrypt/src/bio_m_mem.c create mode 100644 wolfcrypt/src/bio_m_null.c create mode 100644 wolfcrypt/src/bio_m_sock.c diff --git a/src/include.am b/src/include.am index c65e8d263..f0f7ac89a 100644 --- a/src/include.am +++ b/src/include.am @@ -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 diff --git a/src/internal.c b/src/internal.c index 0dca6aaec..f2c9288ac 100644 --- a/src/internal.c +++ b/src/internal.c @@ -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; } diff --git a/src/ssl.c b/src/ssl.c index 4973ac80a..839290b51 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -221,7 +221,6 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) return ssl; } - void wolfSSL_free(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_free"); @@ -230,6 +229,69 @@ void wolfSSL_free(WOLFSSL* ssl) WOLFSSL_LEAVE("SSL_free", 0); } +#ifdef OPENSSL_EXTRA +WOLFSSL* wolfSSL_dup(WOLFSSL* s) +{ + WOLFSSL *ret; + + if (s == NULL) { + WOLFSSL_ERROR(BAD_FUNC_ARG); + return NULL; + } + + ret = wolfSSL_new(s->ctx); + if (ret == NULL) { + WOLFSSL_ERROR(MEMORY_E); + return NULL; + } + + if (DupSSL(ret, s) != 0) { + WOLFSSL_MSG("DupSSL failed\n"); + wolfSSL_free(ret); + return NULL; + } + + /* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */ + if (DupSession(ret, s) != SSL_SUCCESS) { + WOLFSSL_MSG("DupSession failed\n"); + wolfSSL_free(ret); + return NULL; + } + + XMEMCPY(ret->keys.server_write_IV, s->keys.server_write_IV, + CHACHA20_IMP_IV_SZ); + XMEMCPY(ret->keys.client_write_IV, s->keys.client_write_IV, + CHACHA20_IMP_IV_SZ); + + XMEMCPY(ret->keys.aead_enc_imp_IV, ret->keys.server_write_IV, + CHACHA20_IMP_IV_SZ); + XMEMCPY(ret->keys.aead_dec_imp_IV, ret->keys.client_write_IV, + CHACHA20_IMP_IV_SZ); + + /* setup biord, and biowr */ + if (s->biord != NULL) { + if (!WOLFCRYPT_BIO_dup_state(s->biord, &ret->biord)) { + wolfSSL_free(ret); + return NULL; + } + } + + if (s->biowr != NULL) { + if (s->biowr != s->biord) { + if (!WOLFCRYPT_BIO_dup_state(s->biowr, &ret->biowr)) { + wolfSSL_free(ret); + return NULL; + } + } + else + ret->biowr = ret->biord; + } + + return ret; +} +#endif /* OPENSSL_EXTRA */ + + #ifdef HAVE_POLY1305 /* set if to use old poly 1 for yes 0 to use new poly */ int wolfSSL_use_old_poly(WOLFSSL* ssl, int value) @@ -391,6 +453,7 @@ int wolfSSL_negotiate(WOLFSSL* ssl) int err = SSL_FATAL_ERROR; WOLFSSL_ENTER("wolfSSL_negotiate"); + #ifndef NO_WOLFSSL_SERVER if (ssl->options.side == WOLFSSL_SERVER_END) err = wolfSSL_accept(ssl); @@ -617,7 +680,7 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) { int ret; - WOLFSSL_ENTER("wolfSSL_read_internal()"); + WOLFSSL_ENTER("wolfSSL_read_internal"); if (ssl == NULL || data == NULL || sz < 0) return BAD_FUNC_ARG; @@ -637,7 +700,7 @@ static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) ret = ReceiveData(ssl, (byte*)data, min(sz, OUTPUT_RECORD_SIZE), peek); #endif - WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); + WOLFSSL_LEAVE("wolfSSL_read_internal", ret); if (ret < 0) return SSL_FATAL_ERROR; @@ -1295,9 +1358,10 @@ int wolfSSL_shutdown(WOLFSSL* ssl) byte tmp; WOLFSSL_ENTER("SSL_shutdown()"); - if (ssl == NULL) + if (ssl == NULL) { + WOLFSSL_MSG("Null ssl pointer"); return SSL_FATAL_ERROR; - + } if (ssl->options.quietShutdown) { WOLFSSL_MSG("quiet shutdown, no close notify sent"); return SSL_SUCCESS; @@ -1309,6 +1373,7 @@ int wolfSSL_shutdown(WOLFSSL* ssl) ssl->error = SendAlert(ssl, alert_warning, close_notify); if (ssl->error < 0) { WOLFSSL_ERROR(ssl->error); + WOLFSSL_LEAVE("SSL_shutdown()", SSL_FATAL_ERROR); return SSL_FATAL_ERROR; } ssl->options.sentNotify = 1; /* don't send close_notify twice */ @@ -6081,7 +6146,8 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, { word16 havePSK = 0; word16 haveAnon = 0; - WOLFSSL_ENTER("SSL_accept()"); + + WOLFSSL_ENTER("wolfSSL_accept"); #ifdef HAVE_ERRNO_H errno = 0; @@ -6105,12 +6171,12 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, #ifndef NO_CERTS /* in case used set_accept_state after init */ if (!havePSK && !haveAnon && - (ssl->buffers.certificate.buffer == NULL || - ssl->buffers.key.buffer == NULL)) { - WOLFSSL_MSG("accept error: don't have server cert and key"); - ssl->error = NO_PRIVATE_KEY; - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; + (ssl->buffers.certificate.buffer == NULL || + ssl->buffers.key.buffer == NULL)) { + WOLFSSL_MSG("accept error: don't have server cert and key"); + ssl->error = NO_PRIVATE_KEY; + WOLFSSL_ERROR(ssl->error); + return SSL_FATAL_ERROR; } #endif @@ -6571,6 +6637,52 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) return SSL_FAILURE; /* session timed out */ } +int DupSession(WOLFSSL* ssl, WOLFSSL* ossl) +{ + if (ssl == NULL || ossl == NULL) + return SSL_FAILURE; + + ssl->session.bornOn = ossl->session.bornOn; + ssl->session.timeout = ossl->session.timeout; + ssl->session.sessionIDSz = ossl->session.sessionIDSz; + XMEMCPY(ssl->session.sessionID, ossl->session.sessionID, ossl->session.sessionIDSz); + XMEMCPY(ssl->session.masterSecret, ossl->session.masterSecret, + sizeof(ossl->session.masterSecret)); + +#ifdef SESSION_CERTS + XMEMCPY(ssl->session.chain, ossl->session.chain, + sizeof(WOLFSSL_X509_CHAIN)); + XMEMCPY(ssl->session.version, ossl->session.version, + sizeof(ProtocolVersion)); + + ssl->session.cipherSuite0 = ossl->session.cipherSuite0; + ssl->session.cipherSuite = ossl->session.cipherSuite; +#endif + +#ifndef NO_CLIENT_CACHE + ssl->session.idLen = ossl->session.idLen; + XMEMCPY(ssl->session.serverID, ossl->session.serverID, + sizeof(ossl->session.serverID)); +#endif +#ifdef HAVE_SESSION_TICKET + ssl->session.ticketLen = ossl->session.ticketLen; + XMEMCPY(ssl->session.ticket, ossl->session.ticket, + sizeof(ossl->session.ticket)); +#endif +#ifdef HAVE_STUNNEL + void *data; + + for (idx = 0; ; idx++) { + data = wolfSSL_SESSION_get_ex_data(ossl->session, idx); + if (data == NULL) + break; + wolfSSL_SESSION_set_ex_data(ssl->session, idx, data); + } +#endif + + return SSL_SUCCESS; +} + #ifdef WOLFSSL_SESSION_STATS static int get_locked_session_stats(word32* active, word32* total, @@ -7549,17 +7661,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) - { - WOLFSSL_ENTER("SSL_set_bio"); - wolfSSL_set_rfd(ssl, rd->fd); - wolfSSL_set_wfd(ssl, wr->fd); - - ssl->biord = rd; - ssl->biowr = wr; - } - - void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, STACK_OF(WOLFSSL_X509_NAME)* names) { @@ -7743,250 +7844,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return SSL_FATAL_ERROR; } - - WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void) - { - static WOLFSSL_BIO_METHOD meth; - - WOLFSSL_ENTER("BIO_f_buffer"); - meth.type = BIO_BUFFER; - - return &meth; - } - - - long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size) - { - /* wolfSSL has internal buffer, compatibility only */ - WOLFSSL_ENTER("BIO_set_write_buffer_size"); - (void)bio; - return size; - } - - - WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) - { - static WOLFSSL_BIO_METHOD meth; - - WOLFSSL_ENTER("BIO_f_ssl"); - meth.type = BIO_SSL; - - return &meth; - } - - - WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF) - { - WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, - DYNAMIC_TYPE_OPENSSL); - - WOLFSSL_ENTER("BIO_new_socket"); - if (bio) { - bio->type = BIO_SOCKET; - bio->close = (byte)closeF; - bio->eof = 0; - bio->ssl = 0; - bio->fd = sfd; - bio->prev = 0; - bio->next = 0; - bio->mem = NULL; - bio->memLen = 0; - } - return bio; - } - - - int wolfSSL_BIO_eof(WOLFSSL_BIO* b) - { - WOLFSSL_ENTER("BIO_eof"); - if (b->eof) - return 1; - - return 0; - } - - - long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF) - { - WOLFSSL_ENTER("BIO_set_ssl"); - b->ssl = ssl; - b->close = (byte)closeF; - /* add to ssl for bio free if SSL_free called before/instead of free_all? */ - - return 0; - } - - - WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) - { - WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, - DYNAMIC_TYPE_OPENSSL); - WOLFSSL_ENTER("BIO_new"); - if (bio) { - bio->type = method->type; - bio->close = 0; - bio->eof = 0; - bio->ssl = NULL; - bio->mem = NULL; - bio->memLen = 0; - bio->fd = 0; - bio->prev = NULL; - bio->next = NULL; - } - return bio; - } - - - int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) - { - if (bio == NULL || p == NULL) - return SSL_FATAL_ERROR; - - *p = bio->mem; - - return bio->memLen; - } - - - WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len) - { - WOLFSSL_BIO* bio = NULL; - if (buf == NULL) - return bio; - - bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); - if (bio == NULL) - return bio; - - bio->memLen = len; - bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); - if (bio->mem == NULL) { - XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); - return NULL; - } - - XMEMCPY(bio->mem, buf, len); - - return bio; - } - - -#ifdef USE_WINDOWS_API - #define CloseSocket(s) closesocket(s) -#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) - #define CloseSocket(s) closesocket(s) - extern int closesocket(int) ; -#else - #define CloseSocket(s) close(s) -#endif - - int wolfSSL_BIO_free(WOLFSSL_BIO* bio) - { - /* unchain?, doesn't matter in goahead since from free all */ - WOLFSSL_ENTER("BIO_free"); - if (bio) { - if (bio->close) { - if (bio->ssl) - wolfSSL_free(bio->ssl); - if (bio->fd) - CloseSocket(bio->fd); - } - if (bio->mem) - XFREE(bio->mem, 0, DYNAMIC_TYPE_OPENSSL); - XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); - } - return 0; - } - - - int wolfSSL_BIO_free_all(WOLFSSL_BIO* bio) - { - WOLFSSL_ENTER("BIO_free_all"); - while (bio) { - WOLFSSL_BIO* next = bio->next; - wolfSSL_BIO_free(bio); - bio = next; - } - return 0; - } - - - int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) - { - int ret; - WOLFSSL* ssl = 0; - WOLFSSL_BIO* front = bio; - - WOLFSSL_ENTER("BIO_read"); - /* already got eof, again is error */ - if (front->eof) - return SSL_FATAL_ERROR; - - while(bio && ((ssl = bio->ssl) == 0) ) - bio = bio->next; - - if (ssl == 0) return BAD_FUNC_ARG; - - ret = wolfSSL_read(ssl, buf, len); - if (ret == 0) - front->eof = 1; - else if (ret < 0) { - int err = wolfSSL_get_error(ssl, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) - front->eof = 1; - } - return ret; - } - - - int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) - { - int ret; - WOLFSSL* ssl = 0; - WOLFSSL_BIO* front = bio; - - WOLFSSL_ENTER("BIO_write"); - /* already got eof, again is error */ - if (front->eof) - return SSL_FATAL_ERROR; - - while(bio && ((ssl = bio->ssl) == 0) ) - bio = bio->next; - - if (ssl == 0) return BAD_FUNC_ARG; - - ret = wolfSSL_write(ssl, data, len); - if (ret == 0) - front->eof = 1; - else if (ret < 0) { - int err = wolfSSL_get_error(ssl, 0); - if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) - front->eof = 1; - } - - return ret; - } - - - WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append) - { - WOLFSSL_ENTER("BIO_push"); - top->next = append; - append->prev = top; - - return top; - } - - - int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) - { - /* for wolfSSL no flushing needed */ - WOLFSSL_ENTER("BIO_flush"); - (void)bio; - return 1; - } - - #endif /* OPENSSL_EXTRA || GOAHEAD_WS */ @@ -8373,8 +8230,30 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) { WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); - (void)ctx; - /* do nothing */ + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; + } + + ctx->macSize = 0; + ctx->macType = 0xff; + } + + /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, + const WOLFSSL_EVP_MD_CTX *in) + { + WOLFSSL_ENTER("EVP_MD_CTX_copy"); + + if (in == NULL || out == NULL) { + WOLFSSL_MSG("Bad function argument"); + return 0; + } + + wolfSSL_EVP_MD_CTX_init(out); + XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX)); + + return SSL_SUCCESS; } const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) @@ -8471,6 +8350,16 @@ int wolfSSL_set_compression(WOLFSSL* ssl) ctx->cipherType = 0xff; /* no init */ ctx->keyLen = 0; ctx->enc = 1; /* start in encrypt mode */ + + ctx->ivUpdate = 0; + ctx->final_used = 0; + ctx->bufLen = 0; + ctx->blockSize = 0; + ctx->padding = 0; + + XMEMSET(ctx->iv, 0, sizeof(ctx->iv)); + XMEMSET(ctx->buf, 0, sizeof(ctx->buf)); + XMEMSET(ctx->final, 0, sizeof(ctx->final)); } } @@ -8479,15 +8368,13 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx) { WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); - if (ctx) { - ctx->cipherType = 0xff; /* no more init */ - ctx->keyLen = 0; - } + + /* reset to initial values */ + wolfSSL_EVP_CIPHER_CTX_init(ctx); return SSL_SUCCESS; } - /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, const WOLFSSL_EVP_CIPHER* type, byte* key, @@ -8514,6 +8401,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { WOLFSSL_MSG(EVP_AES_128_CBC); ctx->cipherType = AES_128_CBC_TYPE; + ctx->padding = 1; + ctx->ivUpdate = 1; + ctx->blockSize = AES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 16; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8533,6 +8425,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { WOLFSSL_MSG(EVP_AES_192_CBC); ctx->cipherType = AES_192_CBC_TYPE; + ctx->padding = 1; + ctx->ivUpdate = 1; + ctx->blockSize = AES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 24; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8552,6 +8449,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { WOLFSSL_MSG(EVP_AES_256_CBC); ctx->cipherType = AES_256_CBC_TYPE; + ctx->padding = 1; + ctx->ivUpdate = 1; + ctx->blockSize = AES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 32; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8572,6 +8474,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { WOLFSSL_MSG(EVP_AES_128_CTR); ctx->cipherType = AES_128_CTR_TYPE; + ctx->padding = 0; + ctx->ivUpdate = 0; + ctx->blockSize = AES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 16; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8591,6 +8498,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { WOLFSSL_MSG(EVP_AES_192_CTR); ctx->cipherType = AES_192_CTR_TYPE; + ctx->padding = 0; + ctx->ivUpdate = 0; + ctx->blockSize = AES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 24; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8610,6 +8522,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { WOLFSSL_MSG(EVP_AES_256_CTR); ctx->cipherType = AES_256_CTR_TYPE; + ctx->padding = 0; + ctx->ivUpdate = 0; + ctx->blockSize = AES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 32; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8633,6 +8550,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { WOLFSSL_MSG(EVP_DES_CBC); ctx->cipherType = DES_CBC_TYPE; + ctx->padding = 1; + ctx->ivUpdate = 1; + ctx->blockSize = DES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 8; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8651,6 +8573,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) { WOLFSSL_MSG(EVP_DES_EDE3_CBC); ctx->cipherType = DES_EDE3_CBC_TYPE; + ctx->padding = 1; + ctx->ivUpdate = 1; + ctx->blockSize = DES_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = 24; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8673,6 +8600,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) XSTRNCMP(type, "ARC4", 4) == 0)) { WOLFSSL_MSG("ARC4"); ctx->cipherType = ARC4_TYPE; + ctx->blockSize = 1; + ctx->bufLen = 0; + ctx->final_used = 0; + ctx->padding = 0; + ctx->ivUpdate = 0; if (ctx->keyLen == 0) /* user may have already set */ ctx->keyLen = 16; /* default to 128 */ if (key) @@ -8685,6 +8617,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { WOLFSSL_MSG(EVP_IDEA_CBC); ctx->cipherType = IDEA_CBC_TYPE; + ctx->padding = 1; + ctx->ivUpdate = 1; + ctx->blockSize = IDEA_BLOCK_SIZE; + ctx->bufLen = 0; + ctx->final_used = 0; ctx->keyLen = IDEA_KEY_SIZE; if (enc == 0 || enc == 1) ctx->enc = enc ? 1 : 0; @@ -8705,6 +8642,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_MSG("NULL cipher"); ctx->cipherType = NULL_CIPHER_TYPE; ctx->keyLen = 0; + ctx->blockSize = 1; + ctx->bufLen = 0; + ctx->final_used = 0; + ctx->padding = 0; + ctx->ivUpdate = 0; ret = 0; /* success */ } @@ -8715,6 +8657,253 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } + /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + byte *dst, int *dstLen, + const byte *src, int len) + { + int ret = 0, notEncLen = 0, fixLen = 0; + WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate"); + + *dstLen = 0; + + if (len <= 0) + return (len == 0); + + /* Push pending data for the decryption case */ + if (!ctx->enc && ctx->final_used) { + XMEMCPY(dst, ctx->final, ctx->blockSize); + dst += ctx->blockSize; + fixLen = 1; + } + + /* No pending data, src len is a multiple of blocksize */ + if (!ctx->bufLen && !(len & (ctx->blockSize-1))) { + ret = wolfSSL_EVP_Cipher(ctx, &dst[*dstLen], (byte*)src, len); + if (ret != SSL_SUCCESS) { + *dstLen = 0; + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; + } + else { + *dstLen = len; + + /* save new iv if required */ + if (ctx->ivUpdate) { + if (ctx->enc) + XMEMCPY(ctx->iv, &dst[*dstLen-ctx->blockSize], + ctx->blockSize); + else + XMEMCPY(ctx->iv, &src[len-ctx->blockSize], + ctx->blockSize); + ctx->ivUpdate = 2; + } + + /* extra operation for decrypt case */ + if (!ctx->enc) + goto decrypt; + else + return SSL_SUCCESS; + } + } + + /* Pending data */ + if (ctx->bufLen) { + /* pending data + src data less than a block + * keep data and return */ + if (ctx->bufLen + len < ctx->blockSize) { + XMEMCPY(&ctx->buf[ctx->bufLen], src, len); + ctx->bufLen += len; + *dstLen = 0; + return SSL_SUCCESS; + } + else { + /* complete pending buffer and encrypt/decrypt it */ + XMEMCPY(&ctx->buf[ctx->bufLen], src, + ctx->blockSize - ctx->bufLen); + ret = wolfSSL_EVP_Cipher(ctx, &dst[*dstLen], + ctx->buf, ctx->blockSize); + if (ret != SSL_SUCCESS) { + *dstLen = 0; + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; + } + + /* save new iv if required */ + if (ctx->ivUpdate) { + if (ctx->enc) + XMEMCPY(ctx->iv, dst, ctx->blockSize); + else + XMEMCPY(ctx->iv, ctx->buf, ctx->blockSize); + ctx->ivUpdate = 2; + } + + len -= (ctx->blockSize - ctx->bufLen); + src += (ctx->blockSize - ctx->bufLen); + *dstLen = ctx->blockSize; + } + } + /* src len not a multiple of block size */ + else + *dstLen = 0; + + /* encrypt/decrypt max blocks as possible */ + notEncLen = len & (ctx->blockSize - 1); + len -= notEncLen; + if (len > 0) { + ret = wolfSSL_EVP_Cipher(ctx, &dst[*dstLen], (byte*)src, len); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; + } + *dstLen += len; + + /* save new iv if required */ + if (ctx->ivUpdate) { + if (ctx->enc) + XMEMCPY(ctx->iv, &dst[*dstLen-ctx->blockSize], + ctx->blockSize); + else + XMEMCPY(ctx->iv, &src[len-ctx->blockSize], ctx->blockSize); + ctx->ivUpdate = 2; + } + } + + /* save pending data */ + if (notEncLen) + XMEMCPY(ctx->buf, src+len, notEncLen); + ctx->bufLen = notEncLen; + +decrypt: + /* extra operation for decrypt case */ + if (!ctx->enc) { + /* keep last block for final step when decrypting + * multiple of block size */ + if (ctx->blockSize > 1 && !ctx->bufLen) { + *dstLen -= ctx->blockSize; + ctx->final_used = 1; + XMEMCPY(ctx->final, &dst[*dstLen], ctx->blockSize); + } + else + ctx->final_used = 0; + + if (fixLen) + *dstLen += ctx->blockSize; + } + + return SSL_SUCCESS; + } + + /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + byte *dst, int *dstLen) + { + int ret; + + if (ctx->blockSize == 1) { + *dstLen = 0; + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal: blocksize 1"); + return SSL_SUCCESS; + } + + if (ctx->enc) { + if (ctx->padding) { + /* add padding */ + XMEMSET(ctx->buf+ctx->bufLen, (byte)(ctx->blockSize-ctx->bufLen), + ctx->blockSize-ctx->bufLen); + + ret = wolfSSL_EVP_Cipher(ctx, dst, ctx->buf, ctx->blockSize); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal failure"); + return 0; + } + + *dstLen = ctx->blockSize; + } + else { + if (ctx->bufLen) { + ret = wolfSSL_EVP_Cipher(ctx, dst, ctx->buf, ctx->bufLen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal failure"); + return 0; + } + + *dstLen = ctx->bufLen; + } + else { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal: Nothing to do"); + *dstLen = 0; + } + } + } + else { + int i, pad; + + /* decrypt pending data, case of stream cipher */ + if (ctx->bufLen && !ctx->final_used) { + ret = wolfSSL_EVP_Cipher(ctx, dst, ctx->buf, ctx->bufLen); + if (ret != SSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal failure"); + return 0; + } + + *dstLen = ctx->bufLen; + ctx->bufLen = 0; + + return SSL_SUCCESS; + } + else if (ctx->bufLen || !ctx->final_used) { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal: Wrong final block length"); + return 0; + } + + /* get padding */ + if (ctx->padding) { + pad = (int)ctx->final[ctx->blockSize-1]; + if (!pad || pad > (int)ctx->blockSize) { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal: Bad decrypt"); + return 0; + } + + /* check padding */ + for (i = 0; i < pad; i++) { + if (ctx->final[ctx->blockSize-1-i] != pad) { + WOLFSSL_MSG("wolfSSL_EVP_CipherFinal: Bad decrypt"); + return 0; + } + } + + /* return data without padding */ + *dstLen = ctx->blockSize-pad; + XMEMCPY(dst, ctx->final, *dstLen); + } + else { + /* return data */ + *dstLen = ctx->blockSize; + XMEMCPY(dst, ctx->final, *dstLen); + } + } + + return SSL_SUCCESS; + } + + /* return SSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_CIPHER_CTX_copy(WOLFSSL_EVP_CIPHER_CTX *out, + const WOLFSSL_EVP_CIPHER_CTX *in) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_copy"); + + if (in == NULL || out == NULL) { + WOLFSSL_MSG("Bad function argument"); + return 0; + } + + wolfSSL_EVP_CIPHER_CTX_cleanup(out); + XMEMCPY(out, in, sizeof(WOLFSSL_EVP_CIPHER_CTX)); + + return SSL_SUCCESS; + } + /* SSL_SUCCESS on ok */ int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx) { @@ -8764,6 +8953,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) case AES_192_CBC_TYPE : case AES_256_CBC_TYPE : WOLFSSL_MSG("AES CBC"); + if (ctx->ivUpdate > 1) { + ret = wc_AesSetIV(&ctx->cipher.aes, ctx->iv); + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; /* failure */ + } + } + if (ctx->enc) ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len); else @@ -8782,6 +8979,9 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifndef NO_DES3 case DES_CBC_TYPE : + if (ctx->ivUpdate > 1) + wc_Des_SetIV(&ctx->cipher.des, ctx->iv); + if (ctx->enc) wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len); else @@ -8789,6 +8989,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) break; case DES_EDE3_CBC_TYPE : + if (ctx->ivUpdate > 1) { + ret = wc_Des3_SetIV(&ctx->cipher.des3, ctx->iv); + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; /* failure */ + } + } + if (ctx->enc) ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); else @@ -8804,6 +9012,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) #ifdef HAVE_IDEA case IDEA_CBC_TYPE : + if (ctx->ivUpdate > 1) { + ret = wc_IdeaSetIV(&ctx->cipher.idea, ctx->iv); + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; /* failure */ + } + } + if (ctx->enc) wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len); else @@ -8962,7 +9178,6 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return SSL_SUCCESS; } - /* SSL_SUCCESS on ok */ int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type) @@ -8970,23 +9185,27 @@ int wolfSSL_set_compression(WOLFSSL* ssl) WOLFSSL_ENTER("EVP_DigestInit"); if (XSTRNCMP(type, "SHA256", 6) == 0) { ctx->macType = SHA256; + ctx->macSize = SHA256_DIGEST_SIZE; wolfSSL_SHA256_Init((SHA256_CTX*)&ctx->hash); } #ifdef WOLFSSL_SHA384 else if (XSTRNCMP(type, "SHA384", 6) == 0) { ctx->macType = SHA384; + ctx->macSize = SHA384_DIGEST_SIZE; wolfSSL_SHA384_Init((SHA384_CTX*)&ctx->hash); } #endif #ifdef WOLFSSL_SHA512 else if (XSTRNCMP(type, "SHA512", 6) == 0) { ctx->macType = SHA512; + ctx->macSize = SHA512_DIGEST_SIZE; wolfSSL_SHA512_Init((SHA512_CTX*)&ctx->hash); } #endif #ifndef NO_MD5 else if (XSTRNCMP(type, "MD5", 3) == 0) { ctx->macType = MD5; + ctx->macSize = MD5_DIGEST_SIZE; wolfSSL_MD5_Init((MD5_CTX*)&ctx->hash); } #endif @@ -8994,6 +9213,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) /* has to be last since would pick or 256, 384, or 512 too */ else if (XSTRNCMP(type, "SHA", 3) == 0) { ctx->macType = SHA; + ctx->macSize = SHA_DIGEST_SIZE; wolfSSL_SHA_Init((SHA_CTX*)&ctx->hash); } #endif /* NO_SHA */ @@ -10669,47 +10889,6 @@ void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4) #endif /* NO_MD4 */ - -WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) -{ - (void)top; - return 0; -} - - -int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) -{ - (void)bio; - return 0; -} - - - -WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void) -{ - static WOLFSSL_BIO_METHOD meth; - - WOLFSSL_ENTER("BIO_s_mem"); - meth.type = BIO_MEMORY; - - return &meth; -} - - -WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void) -{ - return 0; -} - - -void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags) -{ - (void)bio; - (void)flags; -} - - - void wolfSSL_RAND_screen(void) { @@ -11295,13 +11474,6 @@ void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, #endif /* NO_DES3 */ -int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...) -{ - (void)bio; - (void)format; - return 0; -} - int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) { @@ -16353,23 +16525,6 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return 0; } - - int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { - (void)b; - (void)name; - WOLFSSL_ENTER("wolfSSL_BIO_read_filename"); - WOLFSSL_STUB("wolfSSL_BIO_read_filename"); - - return 0; - } - - WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) { - WOLFSSL_ENTER("wolfSSL_BIO_s_file"); - WOLFSSL_STUB("wolfSSL_BIO_s_file"); - - return NULL; - } - const char * wolf_OBJ_nid2sn(int n) { (void)n; WOLFSSL_ENTER("wolf_OBJ_nid2sn"); @@ -16593,16 +16748,6 @@ int wolf_OBJ_txt2nid(const char* s) { } -WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) { - (void)filename; - (void)mode; - WOLFSSL_ENTER("wolfSSL_BIO_new_file"); - WOLFSSL_STUB("wolfSSL_BIO_new_file"); - - return NULL; -} - - WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, pem_password_cb *cb, void *u) { (void) bp; @@ -16690,7 +16835,6 @@ int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) return SSL_FAILURE; } - int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, CRYPTO_free_func* cb3) { diff --git a/wolfcrypt/src/bio.c b/wolfcrypt/src/bio.c new file mode 100644 index 000000000..b5734002f --- /dev/null +++ b/wolfcrypt/src/bio.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#include +#include + +#ifdef NO_INLINE + #include +#else + #include +#endif + +#include + +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 */ diff --git a/wolfcrypt/src/bio_f_b64.c b/wolfcrypt/src/bio_f_b64.c new file mode 100644 index 000000000..0005f1175 --- /dev/null +++ b/wolfcrypt/src/bio_f_b64.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include +#include + +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 */ diff --git a/wolfcrypt/src/bio_f_buff.c b/wolfcrypt/src/bio_f_buff.c new file mode 100644 index 000000000..255325be5 --- /dev/null +++ b/wolfcrypt/src/bio_f_buff.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include + +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 */ diff --git a/wolfcrypt/src/bio_f_cipher.c b/wolfcrypt/src/bio_f_cipher.c new file mode 100644 index 000000000..e7d040c22 --- /dev/null +++ b/wolfcrypt/src/bio_f_cipher.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include +#include + +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 */ diff --git a/wolfcrypt/src/bio_f_dgst.c b/wolfcrypt/src/bio_f_dgst.c new file mode 100644 index 000000000..f67367b34 --- /dev/null +++ b/wolfcrypt/src/bio_f_dgst.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include +#include + +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 */ \ No newline at end of file diff --git a/wolfcrypt/src/bio_f_sock.c b/wolfcrypt/src/bio_f_sock.c new file mode 100644 index 000000000..b91984f8d --- /dev/null +++ b/wolfcrypt/src/bio_f_sock.c @@ -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 +#endif + +#include +#include +#include +#include + +#ifdef USE_WINDOWS_API +#include +#include +#else +#include +#include +#ifdef SO_NOSIGPIPE +#include +#endif +#endif /* USE_WINDOWS_API */ + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +/* 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 */ diff --git a/wolfcrypt/src/bio_f_ssl.c b/wolfcrypt/src/bio_f_ssl.c new file mode 100644 index 000000000..680dc7f4c --- /dev/null +++ b/wolfcrypt/src/bio_f_ssl.c @@ -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 +#endif + +#include +#include + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include + +#include + +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 */ diff --git a/wolfcrypt/src/bio_m_accept.c b/wolfcrypt/src/bio_m_accept.c new file mode 100644 index 000000000..8c0f61928 --- /dev/null +++ b/wolfcrypt/src/bio_m_accept.c @@ -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 +#endif + +#include +#include +#include +#include + +#ifdef USE_WINDOWS_API +#include +#include +#endif /* USE_WINDOWS_API */ + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +/* 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 */ diff --git a/wolfcrypt/src/bio_m_conn.c b/wolfcrypt/src/bio_m_conn.c new file mode 100644 index 000000000..56386af99 --- /dev/null +++ b/wolfcrypt/src/bio_m_conn.c @@ -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 +#endif + +#include +#include +#include +#include + +#ifdef USE_WINDOWS_API +#include +#include +#endif /* USE_WINDOWS_API */ + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +/* 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 */ diff --git a/wolfcrypt/src/bio_m_dgram.c b/wolfcrypt/src/bio_m_dgram.c new file mode 100644 index 000000000..e9016a04c --- /dev/null +++ b/wolfcrypt/src/bio_m_dgram.c @@ -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 +#endif + +#include +#include +#include +#include + +#ifdef USE_WINDOWS_API +#include +#include +#else +#include +#endif /* USE_WINDOWS_API */ + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +/* 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 */ diff --git a/wolfcrypt/src/bio_m_fd.c b/wolfcrypt/src/bio_m_fd.c new file mode 100644 index 000000000..60dc6951b --- /dev/null +++ b/wolfcrypt/src/bio_m_fd.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +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 */ diff --git a/wolfcrypt/src/bio_m_file.c b/wolfcrypt/src/bio_m_file.c new file mode 100644 index 000000000..d3bdebd11 --- /dev/null +++ b/wolfcrypt/src/bio_m_file.c @@ -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 +#endif + +#include + +#include + +#ifdef OPENSSL_EXTRA + +#ifndef NO_FILESYSTEM + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include + + +/* TO BE REMOVED */ +#ifndef XFERROR +#define XFERROR ferror +#endif + +#ifndef XFILENO +#define XFILENO fileno +#endif + +#if defined(USE_WINDOWS_API) +#include + #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 */ diff --git a/wolfcrypt/src/bio_m_mem.c b/wolfcrypt/src/bio_m_mem.c new file mode 100644 index 000000000..c54ec07d2 --- /dev/null +++ b/wolfcrypt/src/bio_m_mem.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include +#include + + +/* 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 */ diff --git a/wolfcrypt/src/bio_m_null.c b/wolfcrypt/src/bio_m_null.c new file mode 100644 index 000000000..0f2ae47bb --- /dev/null +++ b/wolfcrypt/src/bio_m_null.c @@ -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 +#endif + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +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 */ diff --git a/wolfcrypt/src/bio_m_sock.c b/wolfcrypt/src/bio_m_sock.c new file mode 100644 index 000000000..c1dac2e61 --- /dev/null +++ b/wolfcrypt/src/bio_m_sock.c @@ -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 +#endif + +#include +#include + +#include + +#ifdef OPENSSL_EXTRA + +#include +#include + +#ifdef NO_INLINE +#include +#else +#include +#endif + +#include + +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 */ diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index f9c02690a..356c55cc0 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -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"; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b025dbf74..814de1bc4 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -94,6 +94,8 @@ #include #include #include + #include + #include #endif @@ -215,6 +217,18 @@ int certext_test(void); #ifdef HAVE_IDEA int idea_test(void); #endif +#ifdef OPENSSL_EXTRA +int evp_test(void); +int bio_b64_test(void); +int bio_md_test(void); +int bio_test(void); +int bio_connect_test(void); +int bio_connect_ssl_test(void); +/* Required human interactions, must be move to API + int bio_accept_ssl_test(void); + int bio_accept_test(void); + */ +#endif /* General big buffer size for many tests. */ #define FOURK_BUF 4096 @@ -586,6 +600,50 @@ int wolfcrypt_test(void* args) printf( "PKCS7signed test passed!\n"); #endif +#ifdef OPENSSL_EXTRA + if ( (ret = bio_md_test()) != 0) + return err_sys("BIO digest test failed !\n", ret); + else + printf( "BIO Digest test passed!\n"); + + if ( (ret = bio_b64_test()) != 0) + return err_sys("B64 test failed !\n", ret); + else + printf( "BIO B64 test passed!\n"); + + if ( (ret = bio_connect_test()) != 0) + return err_sys("BIO Connect test failed !\n", ret); + else + printf( "BIO Connect test passed!\n"); + + if ( (ret = bio_connect_ssl_test()) != 0) + return err_sys("BIO Connect SSL test failed !\n", ret); + else + printf( "BIO Connect SSL test passed!\n"); + + /* Required human interactions, must be move to API + if ( (ret = bio_accept_test()) != 0) + return err_sys("BIO Accept test failed !\n", ret); + else + printf( "BIO Accept test passed!\n"); + + if ( (ret = bio_accept_ssl_test()) != 0) + return err_sys("BIO Accept SSL test failed !\n", ret); + else + printf( "BIO Accept SSL test passed!\n"); + */ + + if ( (ret = evp_test()) != 0) + return err_sys("EVP test failed !\n", ret); + else + printf( "EVP test passed!\n"); + + if ( (ret = bio_test()) != 0) + return err_sys("BIO test failed !\n", ret); + else + printf( "BIO test passed!\n"); +#endif + ((func_args*)args)->return_code = ret; return ret; @@ -5948,6 +6006,1128 @@ int openssl_test(void) return 0; } +static int evp_enc_test(const WOLFSSL_EVP_CIPHER* type) +{ + WOLFSSL_EVP_CIPHER_CTX ctx; + int i, ret, len = 0, loop, outLen, rand_size, witLen; + + byte random[4500], wit[5000], out[5000]; + + byte key[] = {0x9d, 0xbf, 0xe2, 0x11, 0xf9, 0xea, 0x19, 0xf3, + 0x44, 0x2e, 0xae, 0x19, 0x54, 0x80, 0x87, 0x4c, + 0x9d, 0xbf, 0xe2, 0x11, 0xf9, 0xea, 0x19, 0xf3, + 0x44, 0x2e, 0xae, 0x19, 0x54, 0x80, 0x87, 0x4c}; + byte iv[] = {0xde, 0xf9, 0x6b, 0x91, 0xda, 0x51, 0x71, 0x80, + 0x47, 0xc9, 0x68, 0xe5, 0xd7, 0x07, 0x85, 0x15}; + + WC_RNG rng; + + i = wc_InitRng(&rng); + if (i != 0) + return -1198; + + i = wc_RNG_GenerateBlock(&rng, random, sizeof(random)); + if (i != 0) + return -1199; + + wc_FreeRng(&rng); + + + /* Encrypt/Decrypt with round bytes block Update */ + for (rand_size = sizeof(random), loop = 1; loop < 1000; loop++) { + rand_size = sizeof(random) - loop; + + /* Encrypt */ + wolfSSL_EVP_CIPHER_CTX_init(&ctx); + + XMEMSET(out, 0, sizeof(out)); + len = 0; + + ret = wolfSSL_EVP_CipherInit(&ctx, type, key, iv, 1); + if (ret != SSL_SUCCESS) + return -1200; + + ret = wolfSSL_EVP_CipherUpdate(&ctx, out+len, &outLen, + random, rand_size); + if (ret != SSL_SUCCESS) + return -1201; + + len += outLen; + + outLen = 0; + ret = wolfSSL_EVP_CipherFinal(&ctx, out+len, &outLen); + if (ret != SSL_SUCCESS) + return -1202; + + /* update final length */ + outLen += len; + + /* Decrypt */ + wolfSSL_EVP_CIPHER_CTX_init(&ctx); + + XMEMSET(wit, 0, sizeof(wit)); + len = 0; + + ret = wolfSSL_EVP_CipherInit(&ctx, type, key, iv, 0); + if (ret != SSL_SUCCESS) + return -1203; + + for (i = 0; i < outLen; i++) + { + witLen = 0; + ret = wolfSSL_EVP_CipherUpdate(&ctx, wit+len, &witLen, out+i, 1); + if (ret != SSL_SUCCESS) + return -1204; + + len += witLen; + } + + witLen = 0; + + ret = wolfSSL_EVP_CipherFinal(&ctx, wit+len, &witLen); + if (ret != SSL_SUCCESS) + return -1205; + + witLen += len; + + if (witLen != rand_size) + return -1206; + + if (XMEMCMP(random, wit, witLen)) + return -1207; + } + + return 0; +} + +int evp_test(void) +{ + int ret; + + //wolfSSL_Debugging_ON(); + +#ifndef NO_AES + ret = evp_enc_test(wolfSSL_EVP_aes_128_cbc()); + if (ret != 0) + return ret; + + ret = evp_enc_test(wolfSSL_EVP_aes_192_cbc()); + if (ret != 0) + return ret; + + ret = evp_enc_test(wolfSSL_EVP_aes_256_cbc()); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_AES_COUNTER + ret = evp_enc_test(wolfSSL_EVP_aes_128_ctr()); + if (ret != 0) + return ret; + + ret = evp_enc_test(wolfSSL_EVP_aes_192_ctr()); + if (ret != 0) + return ret; + + ret = evp_enc_test(wolfSSL_EVP_aes_256_ctr()); + if (ret != 0) + return ret; +#endif /* WOLFSSL_AES_COUNTER */ +#endif /* NO_AES */ + +#ifndef NO_RC4 + ret = evp_enc_test(wolfSSL_EVP_rc4()); + if (ret != 0) + return ret; +#endif /* NO_RC4 */ + +#ifndef NO_DES3 + ret = evp_enc_test(wolfSSL_EVP_des_cbc()); + if (ret != 0) + return ret; + + ret = evp_enc_test(wolfSSL_EVP_des_ede3_cbc()); + if (ret != 0) + return ret; +#endif /* NO_DES3 */ + +#ifdef HAVE_IDEA + ret = evp_enc_test(wolfSSL_EVP_idea_cbc()); + if (ret != 0) + return ret; +#endif /* HAVE_IDEA */ + + return 0; +} + +int bio_md_test(void) +{ + WOLFCRYPT_BIO *bmd, *bnull; + int i, size, total, w; + char digest[SHA512_DIGEST_SIZE]; + + struct bio_digest { + const WOLFSSL_EVP_MD *type; + const char *data; + const char *digest; + } hash_list[] = { +#ifndef NO_MD5 + { + wolfSSL_EVP_md5(), + "1234567890123456789012345678901234567890123456789012345678" + "9012345678901234567890", + "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6" + "\x7a" + }, +#endif +#ifndef NO_SHA + { + wolfSSL_EVP_sha1(), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaa", + "\xAD\x5B\x3F\xDB\xCB\x52\x67\x78\xC2\x83\x9D\x2F\x15\x1E\xA7" + "\x53\x99\x5E\x26\xA0" + }, +#endif +#ifdef WOLFSSL_SHA256 + { + wolfSSL_EVP_sha256(), + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "\x24\x8D\x6A\x61\xD2\x06\x38\xB8\xE5\xC0\x26\x93\x0C\x3E\x60" + "\x39\xA3\x3C\xE4\x59\x64\xFF\x21\x67\xF6\xEC\xED\xD4\x19\xDB" + "\x06\xC1" + }, +#endif +#ifdef WOLFSSL_SHA384 + { + wolfSSL_EVP_sha384(), + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b" + "\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0" + "\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91" + "\x74\x60\x39" + }, +#endif +#ifdef WOLFSSL_SHA512 + { + wolfSSL_EVP_sha512(), + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhi" + "jklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14" + "\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88" + "\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4" + "\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b" + "\x87\x4b\xe9\x09" + }, +#endif + { NULL, NULL, NULL } + }; + + i = 0; + while (hash_list[i].type != NULL) + { + /* Create a digest filter BIO */ + bmd = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_md()); + if (bmd == NULL) + return -1065; + + /* set digest algorithm */ + WOLFCRYPT_BIO_set_md(bmd, hash_list[i].type); + + /* create a null bio to chain with digest */ + bnull = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_null()); + if (bmd == NULL) + return -1066; + + if (WOLFCRYPT_BIO_push(bmd, bnull) == NULL) + return -1067; + + size = (int)strlen(hash_list[i].data); + + /* This loop writes the data to the digest. + * It checks for errors as if the underlying file were non-blocking */ + for (total = 0; total < size; total += w) + { + w = WOLFCRYPT_BIO_write(bmd, hash_list[i].data + total, + size - (int)total); + if (w <= 0) { + if (WOLFCRYPT_BIO_should_retry(bmd)) { + w = 0; + continue; + } + break; + } + } + + if (total != size) + return -1068; + + /* Ensure all of our data is pushed all the way to the BIO */ + WOLFCRYPT_BIO_flush(bmd); + + /* get the digest */ + XMEMSET(digest, 0, sizeof(digest)); + size = WOLFCRYPT_BIO_gets(bmd, digest, sizeof(digest)); + if (size <= 0) + return -1069; + + if (size != wolfSSL_EVP_MD_size(hash_list[i].type)) + return -1070; + + if (XMEMCMP(digest, hash_list[i].digest, size)) + return -1071; + + /* free BIO */ + WOLFCRYPT_BIO_free_all(bmd); + + i++; + } + + return 0; +} + +int bio_b64_test(void) +{ + WOLFCRYPT_BIO *b64, *file; + int i, loop, rand_size; + int total, w; + byte random[9000], wit[9000]; + WC_RNG rng; + + i = wc_InitRng(&rng); + if (i != 0) + return -1198; + + i = wc_RNG_GenerateBlock(&rng, random, sizeof(random)); + if (i != 0) + return -1199; + + wc_FreeRng(&rng); + + /* Encode/Decode random data */ + for (rand_size = sizeof(random), loop = 1; loop < 1000; loop++) { + rand_size = sizeof(random) - loop; + + /* Create a buffered file BIO for writing */ + if (loop & 1) + file = WOLFCRYPT_BIO_new_file("test_b64", "w"); + else + file = WOLFCRYPT_BIO_new_file("test_b64_nonl", "w"); + if (file == NULL) + return -1062; + + /* Create a base64 encoding filter BIO */ + b64 = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_base64()); + if (b64 == NULL) + return -1065; + + if (WOLFCRYPT_BIO_push(b64, file) == NULL) + return -1069; + + /* This loop writes the data to the file. + * It checks for errors as if the underlying file were non-blocking */ + for (total = 0; total < rand_size; total += w) + { + w = WOLFCRYPT_BIO_write(b64, random + total, + rand_size - (int)total); + if (w <= 0) { + if (WOLFCRYPT_BIO_should_retry(b64)) { + w = 0; + continue; + } + break; + } + } + + /* Ensure all of our data is pushed all the way to the file */ + WOLFCRYPT_BIO_flush(b64); + + /* free BIO chain cipher-file */ + WOLFCRYPT_BIO_free_all(b64); + + /* Start read / decode phase */ + + /* Create a buffered file BIO for writing */ + if (loop & 1) + file = WOLFCRYPT_BIO_new_file("test_b64", "r"); + else + file = WOLFCRYPT_BIO_new_file("test_b64_nonl", "r"); + if (file == NULL) + return -1070; + + /* Create a base64 encoding filter BIO */ + b64 = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_base64()); + if (b64 == NULL) + return -1073; + + if (WOLFCRYPT_BIO_push(b64, file) == NULL) + return -1074; + + XMEMSET(wit, 0, sizeof(wit)); + for (total = 0; ; total += w) + { + w = WOLFCRYPT_BIO_read(b64, wit+total, + (int)sizeof(wit) - (int)total); + if (w <= 0) { + if (WOLFCRYPT_BIO_should_retry(b64)) { + w = 0; + continue; + } + break; + } + } + + /* free BIO chain b64-file */ + WOLFCRYPT_BIO_free_all(b64); + + /* check decoded data */ + if (total != rand_size) + return -1079; + + if (XMEMCMP(random, wit, total)) + return -1080; + } + + remove("test_b64"); + remove("test_b64_nonl"); + return 0; +} + +static int bio_filter_test(const WOLFSSL_EVP_CIPHER* cipher_type) +{ + int total, i, w, rand_size; + WOLFCRYPT_BIO *cipher, *buffer, *file, *b64; + byte key[] = { 0x63, 0x21, 0x5f, 0x9b, 0xdc, 0x74, 0xcc, 0x90, + 0x96, 0x43, 0xd1, 0xcc, 0x7a, 0xb2, 0x27, 0xc5 }; + byte iv[] = { 0x1a, 0x4a, 0xf8, 0xd5, 0xd0, 0x09, 0xff, 0x09, + 0xd6, 0xb3, 0x72, 0x3d, 0xc4, 0xed, 0x9c, 0x8e }; + + byte random[4200], wit[4200]; + + WC_RNG rng; + + w = wc_InitRng(&rng); + if (w != 0) + return 1060; + + w = wc_RNG_GenerateBlock(&rng, random, sizeof(random)); + if (w != 0) + return 1061; + + wc_FreeRng(&rng); + + for (rand_size = sizeof(random), i = 1; i < 300; i++) { + + rand_size = sizeof(random) - i; + + /* Create a buffered file BIO for writing */ + if (i & 1) + file = WOLFCRYPT_BIO_new_file("test_assembling_nonl", "w"); + else + file = WOLFCRYPT_BIO_new_file("test_assembling", "w"); + if (file == NULL) + return -1062; + + /* Create a buffering filter BIO to buffer writes to the file */ + buffer = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_buffer()); + if (buffer == NULL) + return -1063; + + /* Create a cipher filter BIO */ + cipher = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_cipher()); + if (cipher == NULL) + return -1064; + + /* Create a base64 encoding filter BIO */ + b64 = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_base64()); + if (b64 == NULL) + return -1065; + + if (i & 1) + WOLFCRYPT_BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + /* Start encrypt / write phase */ + + /* Set cipher key and encryption mode */ + WOLFCRYPT_BIO_set_cipher(cipher, cipher_type, key, iv, 1); + + /* Assemble the BIO chain to be in the order cipher-base64-buffer-file */ + + if (WOLFCRYPT_BIO_push(cipher, b64) == NULL) + return -1066; + + if (WOLFCRYPT_BIO_push(b64, buffer) == NULL) + return -1067; + + if (WOLFCRYPT_BIO_push(buffer, file) == NULL) + return -1068; + + + /* This loop writes the data to the file. + * It checks for errors as if the underlying file were non-blocking */ + for (total = 0; total < rand_size; total += w) + { + w = WOLFCRYPT_BIO_write(cipher, random + total, + rand_size - (int)total); + if (w <= 0) { + if (WOLFCRYPT_BIO_should_retry(cipher)) { + w = 0; + continue; + } + break; + } + } + + /* Ensure all of our data is pushed all the way to the file */ + WOLFCRYPT_BIO_flush(cipher); + + /* get b64 BIO to free it only at first (test purpose) */ + WOLFCRYPT_BIO_pop(b64); + + /* free b64 BIO */ + WOLFCRYPT_BIO_free(b64); + + /* free BIO chain cipher-base64-buffer-file */ + WOLFCRYPT_BIO_free_all(cipher); + + /* Start read / decrypt phase */ + + /* Create a buffered file BIO for writing */ + if (i & 1) + file = WOLFCRYPT_BIO_new_file("test_assembling_nonl", "r"); + else + file = WOLFCRYPT_BIO_new_file("test_assembling", "r"); + if (file == NULL) + return -1070; + + /* Create a buffering filter BIO to buffer writes to the file */ + buffer = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_buffer()); + if (buffer == NULL) + return -1071; + + /* Create a cipher filter BIO */ + cipher = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_cipher()); + if (cipher == NULL) + return -1072; + + /* Create a base64 encoding filter BIO */ + b64 = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_base64()); + if (b64 == NULL) + return -1073; + + if (i & 1) + WOLFCRYPT_BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + + /* Set cipher key and decryption mode */ + WOLFCRYPT_BIO_set_cipher(cipher, cipher_type, key, iv, 0); + + if (WOLFCRYPT_BIO_push(cipher, b64) == NULL) + return -1074; + + if (WOLFCRYPT_BIO_push(b64, buffer) == NULL) + return -1075; + + if (WOLFCRYPT_BIO_push(buffer, file) == NULL) + return -1077; + + /* This loop read the data from the file. + * It checks for errors as if the underlying file were non-blocking */ + XMEMSET(wit, 0, sizeof(wit)); + + for (total = 0; ; total += w) + { + w = WOLFCRYPT_BIO_read(cipher, wit+total, + (int)sizeof(wit) - (int)total); + if (w <= 0) { + if (WOLFCRYPT_BIO_should_retry(cipher)) { + w = 0; + continue; + } + break; + } + } + + if (!WOLFCRYPT_BIO_get_cipher_status(cipher)) + return -1078; + + /* get b64 BIO to free it only at first (test purpose) */ + WOLFCRYPT_BIO_pop(b64); + + /* free b64 BIO */ + WOLFCRYPT_BIO_free(b64); + + /* free BIO chain cipher-buffer-file */ + WOLFCRYPT_BIO_free_all(cipher); + + /* check decrypted data */ + if (total != rand_size) + return -1079; + + if (XMEMCMP(random, wit, total)) + return -1080; + } + + remove("test_assembling_nonl"); + remove("test_assembling"); + + return 0; +} + +int bio_connect_test(void) +{ + WOLFCRYPT_BIO *cbio; + int len; + char buf[1024]; + + cbio = WOLFCRYPT_BIO_new_connect("www.wolfssl.com:http"); + if (cbio == NULL) + return -3000; + + if (WOLFCRYPT_BIO_do_connect(cbio) <= 0) { + fprintf(stderr, "Error connecting to server\n"); + return -3002; + } + + WOLFCRYPT_BIO_puts(cbio, "GET / HTTP/1.0\r\n\r\n"); + for(;;) { + len = WOLFCRYPT_BIO_read(cbio, buf, sizeof(buf)); + if (len == 0) + break; + else if (len < 0) + return -3003; + } + + WOLFCRYPT_BIO_free(cbio); + + return 0; +} +/* Required human interactions, must be move to API */ +#if 0 +int bio_accept_test(void) +{ + + WOLFCRYPT_BIO *abio, *cbio, *cbio2; + char buf[256]; + int r; + + abio = WOLFCRYPT_BIO_new_accept("4444"); + + /* force SO_REUSEADDR */ + WOLFCRYPT_BIO_set_bind_mode(abio, 2); + + /* force NO_SIGPIPE and TCP_NODELAY */ + WOLFCRYPT_BIO_set_socket_options(abio, 3); + + /* First call to WOLFCRYPT_BIO_accept() sets up accept BIO */ + if (WOLFCRYPT_BIO_do_accept(abio) <= 0) { + fprintf(stderr, "Error setting up accept\n"); + return -4000; + } + printf("WOLFCRYPT_BIO_do_accept 1\n"); + + /* Wait for incoming connection */ + if (WOLFCRYPT_BIO_do_accept(abio) <= 0) { + fprintf(stderr, "Error accepting connection\n"); + return -4001; + } + fprintf(stderr, "Connection 1 established\n"); + + /* Retrieve BIO for connection */ + cbio = WOLFCRYPT_BIO_pop(abio); + WOLFCRYPT_BIO_puts(cbio, "Wait for second client\n"); + + /* Wait for another connection */ + if (WOLFCRYPT_BIO_do_accept(abio) <= 0) { + fprintf(stderr, "Error accepting connection\n"); + return -4002; + } + fprintf(stderr, "Connection 2 established\n"); + + /* Close accept BIO to refuse further connections */ + cbio2 = WOLFCRYPT_BIO_pop(abio); + WOLFCRYPT_BIO_free(abio); + + WOLFCRYPT_BIO_puts(cbio, "Second client arrived, you can send msg\n"); + WOLFCRYPT_BIO_puts(cbio2, "Wait for message of First client\n"); + + /* Read msg CBIO -> CBIO2, CBIO2 and CBIO2 -> CBIO */ + do { + XMEMSET(buf, 0, sizeof(buf)); + r = WOLFCRYPT_BIO_read(cbio, buf, sizeof(buf)); + if (r < 0) + break; + if (r >= 3 && !XSTRNCMP("end", buf, 3)) { + WOLFCRYPT_BIO_puts(cbio, "Peer close discussion\n"); + break; + } + WOLFCRYPT_BIO_puts(cbio2, buf); + + XMEMSET(buf, 0, sizeof(buf)); + r = WOLFCRYPT_BIO_read(cbio2, buf, sizeof(buf)); + if (r < 0) + break; + + if (r >= 3 && !XSTRNCMP("end", buf, 3)) { + WOLFCRYPT_BIO_puts(cbio, "Peer close discussion\n"); + break; + } + WOLFCRYPT_BIO_puts(cbio, buf); + + } while (1); + + /* Close the two established connections */ + WOLFCRYPT_BIO_free(cbio); + WOLFCRYPT_BIO_free(cbio2); + + return 0; +} +#endif + +int bio_connect_ssl_test(void) +{ + WOLFCRYPT_BIO *out = NULL, *ssl_bio = NULL; + WOLFSSL_CTX *ssl_ctx = NULL; + + char request[] = "GET / HTTP/1.0\r\n\r\n"; + char buf[1024 * 10]; + int i, len = (int)strlen(request), idx, ret; + + /* Setup all the global SSL stuff */ + ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_client_method()); + if (ssl_ctx == NULL) + return -3000; + + wolfSSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, 0); + + /* Lets make a SSL structure */ + ssl_bio = WOLFCRYPT_BIO_new_ssl(ssl_ctx, BIO_CLOSE); + if (ssl_bio == NULL) { + ret = -3001; + goto end; + } + + /* Use a connect BIO under the SSL BIO */ + out = WOLFCRYPT_BIO_new_connect("www.google.com:443"); + if (out == NULL) { + ret = -3002; + goto end; + } + + /* start connection */ + if (WOLFCRYPT_BIO_do_connect(out) <= 0) { + fprintf(stderr, "Error connecting to server\n"); + ret = -3003; + goto end; + } + + /* non blocking mode */ + WOLFCRYPT_BIO_set_nbio(out, 1); + + /* Associate connect and ssl BIO */ + out = WOLFCRYPT_BIO_push(ssl_bio, out); + if (out == NULL) { + ret = -3004; + goto end; + } + + for (idx = 0;;) { + i = WOLFCRYPT_BIO_write(out, request+idx, len); + if (i <= 0) { + if (WOLFCRYPT_BIO_should_retry(out)) { + sleep(1); + continue; + } else { + ret = -3005; + goto end; + } + } + idx += i; + len -= i; + if (len <= 0) + break; + } + + for (;;) { + i = WOLFCRYPT_BIO_read(out, buf, sizeof(buf)); + if (i == 0) + break; + if (i < 0) { + if (WOLFCRYPT_BIO_should_retry(out)) { + sleep(1); + continue; + } + ret = -3006; + goto end; + } + fwrite(buf, 1, i, stdout); + } + + ret = 0; + +end: + WOLFCRYPT_BIO_free_all(out); + + if (ssl_ctx != NULL) + wolfSSL_CTX_free(ssl_ctx); + + return ret; +} + +/* Required human interactions, must be move to API */ +#if 0 +int bio_accept_ssl_test(void) +{ + WOLFCRYPT_BIO *ssl_bio = NULL, *in = NULL, *buf_bio = NULL, *b_rw = NULL; + WOLFSSL_CTX *ssl_ctx = NULL; + char buf[512]; + int ret = 1, len, i = 0; + +#ifndef NO_DH + /* dh1024 p */ + static unsigned char p[] = { + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, + }; + + /* dh1024 g */ + static unsigned char g[] = { 0x02 }; +#endif + +#if 1 + #define CERT_F "./certs/server-cert.pem" + #define KEY_F "./certs/server-key.pem" +#endif +#if 0 + #define CERT_F "./certs/server-ecc.pem" + #define KEY_F "./certs/ecc-key.pem" +#endif +#if 0 + #define CERT_F "./certs/server-ecc-rsa.pem" + #define KEY_F "./certs/ecc-key.pem" +#endif + + ssl_ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); + if (ssl_ctx == NULL) + return -3000; + + if (!wolfSSL_CTX_use_certificate_file(ssl_ctx, CERT_F, SSL_FILETYPE_PEM)) { + ret = -3001; + goto end; + } + + if (!wolfSSL_CTX_use_PrivateKey_file(ssl_ctx, KEY_F, SSL_FILETYPE_PEM)) { + ret = -3002; + goto end; + } + + if (!wolfSSL_CTX_check_private_key(ssl_ctx)) { + ret = -3003; + goto end; + } + +#ifndef NO_DH + if (!wolfSSL_CTX_SetTmpDH(ssl_ctx, p, sizeof(p), g, sizeof(g))) { + ret = -3004; + goto end; + } +#endif /* NO_DH */ + + /* Setup server side SSL bio */ + ssl_bio = WOLFCRYPT_BIO_new_ssl(ssl_ctx, 0); + if (ssl_bio == NULL) { + ret = -3005; + goto end; + } + + /* Create the buffering BIO */ + buf_bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_f_buffer()); + if (buf_bio == NULL) { + ret = -3006; + goto end; + } + + /* Add to chain */ + ssl_bio = WOLFCRYPT_BIO_push(buf_bio, ssl_bio); + if (ssl_bio == NULL) { + ret = -3007; + goto end; + } + + in = WOLFCRYPT_BIO_new_accept("4433"); + if (in == NULL) { + ret = -3008; + goto end; + } + + /* force SO_REUSEADDR */ + WOLFCRYPT_BIO_set_bind_mode(in, 2); + + /* force NO_SIGPIPE and TCP_NODELAY */ + WOLFCRYPT_BIO_set_socket_options(in, 3); + + /* By doing this when a new connection is established + * we automatically have ssl_bio inserted into it. The + * BIO chain is now 'swallowed' by the accept BIO and + * will be freed when the accept BIO is freed. + */ + if (WOLFCRYPT_BIO_set_accept_bios(in, ssl_bio) <= 0) { + ret = -3006; + goto end; + } + + while (i++ < 5) { + /* Setup accept BIO */ + if (WOLFCRYPT_BIO_do_accept(in) <= 0) { + fprintf(stderr, "Error setting up accept BIO\n"); + ret = -3010; + goto end; + } + + /* Now wait for incoming connection */ + if (WOLFCRYPT_BIO_do_handshake(in) <= 0) { + fprintf(stderr, "Error in connection\n"); + ret = -3011; + goto end; + } + + b_rw = WOLFCRYPT_BIO_pop(in); + if (b_rw == NULL) { + printf("BIO error -> close\n"); + break; + } + + for(;;) { + len = WOLFCRYPT_BIO_gets(b_rw, buf, sizeof(buf)); + if (len == 0) { + /* + * If we have finished, remove the underlying BIO stack so the + * next time we call any function for this BIO, it will attempt + * to do an accept + */ + printf("Done -> close\n"); + break; + } + else if (len < 0) { + if (WOLFCRYPT_BIO_should_retry(b_rw)) + continue; + printf("Read error -> close\n"); + break; + } + + if (buf[0] == '\r' || buf[0] == '\n') { + WOLFCRYPT_BIO_puts(b_rw, "CLOSE\n"); + WOLFCRYPT_BIO_flush(b_rw); + printf("Done -> close\n"); + break; + } + fprintf(stdout, "Received : '%s'\n", buf); + /* Send response */ + WOLFCRYPT_BIO_puts(b_rw, "ACK: "); + WOLFCRYPT_BIO_puts(b_rw, buf); + WOLFCRYPT_BIO_flush(b_rw); + } + + /* close connection */ + WOLFCRYPT_BIO_free_all(b_rw); + } + + ret = 0; + +end: + if (in != NULL) + WOLFCRYPT_BIO_free_all(in); + + if (ssl_ctx != NULL) + wolfSSL_CTX_free(ssl_ctx); + + return ret; +} +#endif + +int bio_test(void) +{ + WOLFCRYPT_BIO *bio; + int ret; + + const char buf[] = "This is a test of the implementation of OpenSSL BIO"; + char buf_w[200]; + + /* BIO FILE TEST */ + + /* create file */ + bio = WOLFCRYPT_BIO_new_file("test_bio.txt", "w"); + if (bio == NULL) + return -1000; + + /* write */ + ret = WOLFCRYPT_BIO_write(bio, buf, (int)strlen(buf)); + if (ret != (int)strlen(buf)) + return -1001; + + ret = WOLFCRYPT_BIO_puts(bio, "\n"); + if (ret != 1) + return -1002; + + /* close */ + WOLFCRYPT_BIO_free(bio); + + /* open */ + bio = WOLFCRYPT_BIO_new_file("test_bio.txt", "r"); + if (bio == NULL) + return -1003; + + /* read */ + ret = WOLFCRYPT_BIO_read(bio, buf_w, sizeof(buf_w)); + if (ret != (int)strlen(buf)+1) + return -1004; + + if (XMEMCMP(buf, buf_w, ret-1)) + return -1005; + + /* close */ + WOLFCRYPT_BIO_free(bio); + + /* append */ + bio = WOLFCRYPT_BIO_new_file("test_bio.txt", "a+"); + if (bio == NULL) + return -1006; + + ret = WOLFCRYPT_BIO_tell(bio); + if (ret != (int)strlen(buf)+1) + return -1007; + + /* write */ + ret = WOLFCRYPT_BIO_printf(bio, "%s\n", buf); + if (ret != (int)strlen(buf)+1) + return -1008; + + ret = WOLFCRYPT_BIO_tell(bio); + if (ret != 2*((int)strlen(buf)+1)) + return -1009; + + /* reset, before reading */ + ret = WOLFCRYPT_BIO_reset(bio); + if (ret != 0) + return -1010; + + /* read */ + ret = WOLFCRYPT_BIO_read(bio, buf_w, sizeof(buf_w)); + if (ret != 2*((int)strlen(buf)+1)) + return -1011; + + /* close */ + WOLFCRYPT_BIO_free(bio); + + if (XMEMCMP(buf, buf_w, (int)strlen(buf))) + return -1012; + + if (XMEMCMP(buf, buf_w+1+strlen(buf), (int)strlen(buf))) + return -1013; + + /* BIO MEMORY TEST */ + bio = WOLFCRYPT_BIO_new(WOLFCRYPT_BIO_s_mem()); + if (bio == NULL) + return -1050; + + ret = WOLFCRYPT_BIO_puts(bio, buf); + if (ret != (int)strlen(buf)) + return -1051; + + ret = WOLFCRYPT_BIO_gets(bio, buf_w, sizeof(buf_w)); + if (ret != (int)strlen(buf)) + return -1052; + + ret = WOLFCRYPT_BIO_gets(bio, buf_w, sizeof(buf_w)); + if (ret != 0) + return -1053; + + WOLFCRYPT_BIO_reset(bio); + + ret = WOLFCRYPT_BIO_write(bio, buf, (int)strlen(buf)); + if (ret != (int)strlen(buf)) + return -1054; + + ret = WOLFCRYPT_BIO_write(bio, buf, (int)strlen(buf)); + if (ret != (int)strlen(buf)) + return -1055; + + XMEMSET(buf_w, 0, sizeof(buf_w)); + + ret = WOLFCRYPT_BIO_read(bio, buf_w, 5); + ret += WOLFCRYPT_BIO_read(bio, buf_w+5, 9); + ret += WOLFCRYPT_BIO_read(bio, buf_w+14, 17); + ret += WOLFCRYPT_BIO_read(bio, buf_w+31, 7); + + if (ret != 2*(int)strlen(buf)-WOLFCRYPT_BIO_pending(bio)) + return -1059; + + if (XMEMCMP(buf, buf_w, 2*(int)strlen(buf)-WOLFCRYPT_BIO_pending(bio))) + return -1060; + + /* assembling BIO test for all cipher */ +#ifndef NO_AES + ret = bio_filter_test(wolfSSL_EVP_aes_128_cbc()); + if (ret != 0) + return ret; + + ret = bio_filter_test(wolfSSL_EVP_aes_192_cbc()); + if (ret != 0) + return ret; + + ret = bio_filter_test(wolfSSL_EVP_aes_256_cbc()); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_AES_COUNTER + ret = bio_filter_test(wolfSSL_EVP_aes_128_ctr()); + if (ret != 0) + return ret; + + ret = bio_filter_test(wolfSSL_EVP_aes_192_ctr()); + if (ret != 0) + return ret; + + ret = bio_filter_test(wolfSSL_EVP_aes_256_ctr()); + if (ret != 0) + return ret; +#endif /* WOLFSSL_AES_COUNTER */ +#endif /* NO_AES */ + +#ifndef NO_RC4 + ret = bio_filter_test(wolfSSL_EVP_rc4()); + if (ret != 0) + return ret; +#endif /* NO_RC4 */ + +#ifndef NO_DES3 + ret = bio_filter_test(wolfSSL_EVP_des_cbc()); + if (ret != 0) + return ret; + + ret = bio_filter_test(wolfSSL_EVP_des_ede3_cbc()); + if (ret != 0) + return ret; +#endif /* NO_DES3 */ + +#ifdef HAVE_IDEA + ret = bio_filter_test(wolfSSL_EVP_idea_cbc()); + if (ret != 0) + return ret; +#endif /* HAVE_IDEA */ + + return 0; +} + #endif /* OPENSSL_EXTRA */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index bb835db98..c49193441 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -26,6 +26,11 @@ #include #include + +#ifdef OPENSSL_EXTRA +#include +#endif + #ifdef HAVE_CRL #include #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 */ diff --git a/wolfssl/openssl/bio.h b/wolfssl/openssl/bio.h index 5f1d4211d..2680e4c26 100644 --- a/wolfssl/openssl/bio.h +++ b/wolfssl/openssl/bio.h @@ -1,23 +1,564 @@ -/* bio.h for openssl */ +#ifndef WOLFCRYPT_BIO_H_ +#define WOLFCRYPT_BIO_H_ +#include -#ifndef WOLFSSL_BIO_H_ -#define WOLFSSL_BIO_H_ - -#include +#include +#include +#include +#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_ */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 6ea1443e5..70f0f8842 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -46,7 +46,7 @@ #include #include #include - +#include #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*); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 6e965561e..05c76048d 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -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); diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index b7a3c89ac..4b4cdc7ba 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -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 !!! */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 13911d9f8..3e91a3d98 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -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)