summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksii Beketov <ol.beketov@samsung.com>2020-05-12 16:40:52 +0300
committerSudipto <sudipto.bal@samsung.com>2020-06-19 22:30:02 +0530
commit2a0c154b07a2298bc8b353e15c9c9f51aabd32dc (patch)
tree95e1a511113314802df0a00e3c1138714e5a2e18
parent10964d1a88ca6d940aad793653bfea7b460a0a1f (diff)
downloadiotivity-2a0c154b07a2298bc8b353e15c9c9f51aabd32dc.tar.gz
iotivity-2a0c154b07a2298bc8b353e15c9c9f51aabd32dc.tar.bz2
iotivity-2a0c154b07a2298bc8b353e15c9c9f51aabd32dc.zip
Sample HTTPS server
New HTTP secure server sample added. Server loads secure credentials from SVR DB. (cherry-picked from ffe5ae340e426f935a0993ef5971958262b310cb) Change-Id: I6ce4b925b9027184be36122363dc39eb182ecfac Signed-off-by: Oleksii Beketov <ol.beketov@samsung.com> Signed-off-by: Sudipto <sudipto.bal@samsung.com>
-rw-r--r--resource/csdk/security/provisioning/sample/SConscript12
-rw-r--r--resource/csdk/security/provisioning/sample/oic_svr_db_server_https.datbin0 -> 5095 bytes
-rw-r--r--resource/csdk/security/provisioning/sample/sampleserver_https.cpp826
3 files changed, 834 insertions, 4 deletions
diff --git a/resource/csdk/security/provisioning/sample/SConscript b/resource/csdk/security/provisioning/sample/SConscript
index cfde9797f..bd72de943 100644
--- a/resource/csdk/security/provisioning/sample/SConscript
+++ b/resource/csdk/security/provisioning/sample/SConscript
@@ -110,6 +110,7 @@ sampleserver_justworks_protectedDB = provisioning_env.Program('sampleserver_just
sampleserver_randompin = provisioning_env.Program('sampleserver_randompin', 'sampleserver_randompin.cpp')
sampleserver_mfg = provisioning_env.Program('sampleserver_mfg', hwemul_src + ['sampleserver_mfg.cpp'])
sampleserver_mvjustworks = provisioning_env.Program('sampleserver_mvjustworks', 'sampleserver_mvjustworks.cpp')
+sampleserver_https = provisioning_env.Program('sampleserver_https', hwemul_src + ['sampleserver_https.cpp'])
if provisioning_env.get('MULTIPLE_OWNER') == '1':
subownerclient = provisioning_env.Program('subownerclient', 'subownerclient.c')
@@ -146,6 +147,9 @@ randompin_with_emptyuuid_dat = provisioning_env.Install(sec_provisioning_build_d
sec_provisioning_src_dir+ 'oic_svr_db_randompin_with_empty_deviceid.dat')
mvjustworksdat = provisioning_env.Install(sec_provisioning_build_dir,
sec_provisioning_src_dir + 'oic_svr_db_server_mvjustworks.dat')
+httpsdat = provisioning_env.Install(sec_provisioning_build_dir,
+ sec_provisioning_src_dir+ 'oic_svr_db_server_https.dat')
+
if provisioning_env.get('MULTIPLE_OWNER') == '1':
subownerclientdat = provisioning_env.Install(sec_provisioning_build_dir,
@@ -165,17 +169,17 @@ if provisioning_env.get('MULTIPLE_OWNER') == '1':
Alias("samples", [
provisioningclient, subownerclient,
sampleserver_justworks, sampleserver_randompin, sampleserver_mfg,
- sampleserver_preconfpin,sampleserver_justworks_protectedDB,
+ sampleserver_preconfpin, sampleserver_https, sampleserver_justworks_protectedDB,
clientdat, subownerclientdat, preconfserverdat,
- justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat,
+ justworksdat, randompindat, mfgdat, httpsdat, randompin_with_emptyuuid_dat,
mvjustworksdat, justworksDefaultdat, justworksProtectedDBdat_plain
])
else:
Alias("samples", [
provisioningclient,
sampleserver_justworks, sampleserver_randompin, sampleserver_mfg,
- clientdat,sampleserver_justworks_protectedDB,
- justworksdat, randompindat, mfgdat, randompin_with_emptyuuid_dat,
+ clientdat, sampleserver_https, sampleserver_justworks_protectedDB,
+ justworksdat, randompindat, mfgdat, httpsdat, randompin_with_emptyuuid_dat,
mvjustworksdat, justworksDefaultdat, justworksProtectedDBdat_plain
])
diff --git a/resource/csdk/security/provisioning/sample/oic_svr_db_server_https.dat b/resource/csdk/security/provisioning/sample/oic_svr_db_server_https.dat
new file mode 100644
index 000000000..3c6758a97
--- /dev/null
+++ b/resource/csdk/security/provisioning/sample/oic_svr_db_server_https.dat
Binary files differ
diff --git a/resource/csdk/security/provisioning/sample/sampleserver_https.cpp b/resource/csdk/security/provisioning/sample/sampleserver_https.cpp
new file mode 100644
index 000000000..6982d2e26
--- /dev/null
+++ b/resource/csdk/security/provisioning/sample/sampleserver_https.cpp
@@ -0,0 +1,826 @@
+/******************************************************************
+*
+* Copyright 2020 Samsung Electronics All Rights Reserved.
+*
+*
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+******************************************************************/
+///////////////////////////////////////////////////////////////////////
+//NOTE : This sample server is generated based on svrdbeditor.c
+///////////////////////////////////////////////////////////////////////
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_time time
+#define mbedtls_time_t time_t
+#define mbedtls_fprintf fprintf
+#define mbedtls_printf printf
+#define mbedtls_exit exit
+#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
+#endif
+#if defined(MBEDTLS_SSL_CACHE_C)
+#include "mbedtls/ssl_cache.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/certs.h"
+#include "mbedtls/x509.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/net_sockets.h"
+#include "mbedtls/error.h"
+#include "mbedtls/debug.h"
+
+#define HTTP_RESPONSE \
+ "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
+ "<h2>mbed TLS Test Server</h2>\r\n" \
+ "<p>Successful connection using: %s</p>\r\n"
+
+#define DEBUG_LEVEL 0
+
+#if defined(MBEDTLS_CHECK_PARAMS)
+#include "mbedtls/platform_util.h"
+#endif
+
+#include "iotivity_config.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+#include <signal.h>
+#include "ocstack.h"
+#include "logger.h"
+#include "pkix_interface.h"
+#include "casecurityinterface.h"
+#include "utlist.h"
+#include "base64.h"
+#include "octypes.h"
+#include "oic_malloc.h"
+#include "oic_string.h"
+#include "srmresourcestrings.h"
+#include "credresource.h"
+#include "security_internals.h"
+extern "C" {
+#include "psinterface.h"
+}
+
+#define TAG "SAMPLE_HTTPS_PKIX"
+#define PORT "4433"
+
+//Secure Virtual Resource database for Iotivity Server
+//It contains Server's Identity and the manufacturer certificate
+char g_svrDbPath[1024];
+static char CRED_FILE[] = "oic_svr_db_server_https.dat";
+
+FILE* server_fopen(const char *path, const char *mode)
+{
+ (void)path;
+ return fopen(CRED_FILE, mode);
+}
+
+static int ParseCertChain(mbedtls_x509_crt *crt, unsigned char *buf, size_t bufLen)
+{
+ if (NULL == crt || NULL == buf || 0 == bufLen)
+ {
+ OIC_LOG(DEBUG, TAG, "ParseCertChain : Invalid param");
+ return -1;
+ }
+
+ /* byte encoded ASCII string '-----BEGIN CERTIFICATE-----' */
+ char pemCertHeader[] =
+ {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x43, 0x45, 0x52,
+ 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
+ };
+ // byte encoded ASCII string '-----END CERTIFICATE-----' */
+ char pemCertFooter[] =
+ {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
+ 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d
+ };
+ size_t pemCertHeaderLen = sizeof(pemCertHeader);
+ size_t pemCertFooterLen = sizeof(pemCertFooter);
+
+ size_t len = 0;
+ unsigned char *tmp = NULL;
+ int count = 0;
+ int ret = 0;
+ size_t pos = 0;
+
+ while (pos < bufLen)
+ {
+ if (0x30 == buf[pos] && 0x82 == buf[pos + 1])
+ {
+ tmp = (unsigned char *)buf + pos + 1;
+ ret = mbedtls_asn1_get_len(&tmp, buf + bufLen, &len);
+ if (0 != ret)
+ {
+ OIC_LOG_V(DEBUG, TAG, "mbedtls_asn1_get_len failed: 0x%04x", ret);
+ return -1;
+ }
+
+ if (pos + len < bufLen)
+ {
+ ret = mbedtls_x509_crt_parse_der(crt, buf + pos, len + 4);
+ if (0 == ret)
+ {
+ count++;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "mbedtls_x509_crt_parse_der failed: 0x%04x", ret);
+ }
+ }
+ pos += len + 4;
+ }
+ else if ((buf + pos + pemCertHeaderLen < buf + bufLen) &&
+ 0 == memcmp(buf + pos, pemCertHeader, pemCertHeaderLen))
+ {
+ void *endPos = NULL;
+ endPos = memmem(&(buf[pos]), bufLen - pos, pemCertFooter, pemCertFooterLen);
+ if (NULL == endPos)
+ {
+ OIC_LOG(DEBUG, TAG, "end of PEM certificate not found.");
+ return -1;
+ }
+
+ len = (char *)endPos - ((char *)buf + pos) + pemCertFooterLen;
+ if (pos + len + 1 <= bufLen)
+ {
+ char con = buf[pos + len];
+ buf[pos + len] = 0x00;
+ ret = mbedtls_x509_crt_parse(crt, buf + pos, len + 1);
+ if (0 == ret)
+ {
+ count++;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "mbedtls_x509_crt_parse failed: 0x%04x", ret);
+ }
+ buf[pos + len] = con;
+ }
+ else
+ {
+ unsigned char *lastCert = (unsigned char *)OICMalloc((len + 1) * sizeof(unsigned char));
+ if (NULL == lastCert)
+ {
+ OIC_LOG(DEBUG, TAG, "Failed to allocate memory for certificate");
+ return -1;
+ }
+ memcpy(lastCert, buf + pos, len);
+ lastCert[len] = 0x00;
+ ret = mbedtls_x509_crt_parse(crt, lastCert, len + 1);
+ if (0 == ret)
+ {
+ count++;
+ }
+ else
+ {
+ OIC_LOG_V(DEBUG, TAG, "mbedtls_x509_crt_parse failed: 0x%04x", ret);
+ }
+ OICFree(lastCert);
+ }
+ pos += len;
+ }
+ else
+ {
+ pos++;
+ }
+ }
+
+ return 0;
+}
+
+// TODO: Update to use credresource.c
+static void ParseDerCaCert(ByteArray_t *crt, const char *usage, uint16_t credId)
+{
+ if (NULL == crt || NULL == usage)
+ {
+ OIC_LOG(DEBUG, TAG, "ParseDerCaCert : Invalid param");
+ return;
+ }
+ crt->len = 0;
+ OicSecCred_t *temp = NULL;
+
+ LL_FOREACH(((OicSecCred_t *)GetCredList()), temp)
+ {
+ if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
+ 0 == strcmp(temp->credUsage, usage) &&
+ temp->credId == credId)
+ {
+ if (OIC_ENCODING_BASE64 == temp->optionalData.encoding)
+ {
+ size_t bufSize = B64DECODE_OUT_SAFESIZE((temp->optionalData.len + 1));
+ uint8_t *buf = (uint8_t *)OICCalloc(1, bufSize);
+ if (NULL == buf)
+ {
+ OIC_LOG(DEBUG, TAG, "ParseDerCaCert : Failed to allocate memory");
+ return;
+ }
+ uint32_t outSize;
+ if (B64_OK != b64Decode((char *)(temp->optionalData.data), temp->optionalData.len, buf, bufSize,
+ &outSize))
+ {
+ OICFree(buf);
+ OIC_LOG(DEBUG, TAG, "ParseDerCaCert : Failed to decode base64 data");
+ return;
+ }
+ crt->data = (uint8_t *)OICRealloc(crt->data, crt->len + outSize);
+ memcpy(crt->data + crt->len, buf, outSize);
+ crt->len += outSize;
+ OICFree(buf);
+ }
+ else
+ {
+ crt->data = (uint8_t *)OICRealloc(crt->data, crt->len + temp->optionalData.len);
+ memcpy(crt->data + crt->len, temp->optionalData.data, temp->optionalData.len);
+ crt->len += temp->optionalData.len;
+ }
+ }
+ }
+ if (0 == crt->len)
+ {
+ OIC_LOG_V(INFO, TAG, "ParseDerCaCert : %s not found", usage);
+ }
+ return;
+}
+
+// TODO: Update to use credresource.c
+static void ParseDerOwnCert(ByteArray_t *crt, const char *usage, uint16_t credId)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+ if (NULL == crt || NULL == usage)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return;
+ }
+ crt->len = 0;
+ OicSecCred_t *temp = NULL;
+ LL_FOREACH(((OicSecCred_t *)GetCredList()), temp)
+ {
+ if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
+ 0 == strcmp(temp->credUsage, usage) &&
+ temp->credId == credId)
+ {
+ crt->data = (uint8_t *)OICRealloc(crt->data, crt->len + temp->publicData.len);
+ memcpy(crt->data + crt->len, temp->publicData.data, temp->publicData.len);
+ crt->len += temp->publicData.len;
+ OIC_LOG_V(DEBUG, TAG, "%s found", usage);
+ }
+ }
+ if (0 == crt->len)
+ {
+ OIC_LOG_V(WARNING, TAG, "%s not found", usage);
+ }
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return;
+}
+
+inline void ParseDerKey(ByteArray_t *key, const char *usage, uint16_t credId)
+{
+ OIC_LOG_V(DEBUG, TAG, "In %s", __func__);
+ if (NULL == key || NULL == usage)
+ {
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+ return;
+ }
+
+ OicSecCred_t *temp = NULL;
+ key->len = 0;
+ LL_FOREACH(((OicSecCred_t *)GetCredList()), temp)
+ {
+ if (SIGNED_ASYMMETRIC_KEY == temp->credType &&
+ 0 == strcmp(temp->credUsage, usage) &&
+ temp->credId == credId)
+ {
+ key->data = (uint8_t *)OICRealloc(key->data, key->len + temp->privateData.len);
+ memcpy(key->data + key->len, temp->privateData.data, temp->privateData.len);
+ key->len += temp->privateData.len;
+ OIC_LOG_V(DEBUG, TAG, "Key for %s found", usage);
+ }
+ }
+ if (0 == key->len)
+ {
+ OIC_LOG_V(WARNING, TAG, "Key for %s not found", usage);
+ }
+ OIC_LOG_V(DEBUG, TAG, "Out %s", __func__);
+}
+
+void PrintCredList(const OicSecCred_t *creds, mbedtls_x509_crt * crt, mbedtls_pk_context * pkey)
+{
+ const OicSecCred_t *cred = NULL;
+ const OicSecCred_t *tempCred = NULL;
+ bool isEmptyList = true;
+ LL_FOREACH_SAFE(creds, cred, tempCred)
+ {
+ switch (cred->credType)
+ {
+ case SYMMETRIC_PAIR_WISE_KEY:
+ case SYMMETRIC_GROUP_KEY:
+ case ASYMMETRIC_KEY:
+ break;
+ case SIGNED_ASYMMETRIC_KEY:
+ //private data
+ if (cred->privateData.data)
+ {
+ int ret = mbedtls_pk_parse_key(pkey, cred->privateData.data, cred->privateData.len,
+ NULL, 0);
+ if (0 != ret)
+ {
+ OIC_LOG_V(ERROR, TAG, "%s: mbedtls_pk_parse_key returned %d", __func__, ret);
+ return;
+ }
+ }
+
+ //public data
+ if (cred->publicData.data)
+ {
+ if (cred->credUsage &&
+ (0 == strcmp(cred->credUsage, PRIMARY_CERT) ||
+ 0 == strcmp(cred->credUsage, MF_PRIMARY_CERT)))
+ {
+ char buf[2048];
+ mbedtls_x509_crt *tmpCrt = NULL;
+ PkiInfo_t inf;
+ int i = 0;
+
+ memset(&inf, 0x00, sizeof(PkiInfo_t));
+
+ ParseDerOwnCert(&inf.crt, cred->credUsage, cred->credId);
+ ParseCertChain(crt, inf.crt.data, inf.crt.len);
+
+ for (i = 0, tmpCrt = crt; NULL != tmpCrt; i++, tmpCrt = tmpCrt->next)
+ {
+ mbedtls_x509_crt_info( buf, sizeof(buf) - 1, "", tmpCrt );
+ }
+ }
+ else
+ {
+ // TODO: T.B.D
+ }
+ }
+
+ //optional data
+ if (cred->optionalData.data)
+ {
+ //CA chain
+ if (cred->credUsage &&
+ (0 == strcmp(cred->credUsage, TRUST_CA) ||
+ 0 == strcmp(cred->credUsage, MF_TRUST_CA)))
+ {
+ char buf[2048];
+ mbedtls_x509_crt ca;
+ mbedtls_x509_crt *tmpCa = NULL;
+ PkiInfo_t inf;
+ int i = 0;
+
+ memset(&inf, 0x00, sizeof(PkiInfo_t));
+ mbedtls_x509_crt_init(&ca);
+
+ ParseDerCaCert(&inf.ca, cred->credUsage, cred->credId);
+ ParseCertChain(&ca, inf.ca.data, inf.ca.len);
+
+ for (i = 0, tmpCa = &ca; NULL != tmpCa; i++, tmpCa = tmpCa->next)
+ {
+ mbedtls_x509_crt_info( buf, sizeof(buf) - 1, "", tmpCa );
+ }
+ }
+ else
+ {
+ // TODO: T.B.D
+ }
+ }
+ break;
+ case PIN_PASSWORD:
+ case ASYMMETRIC_ENCRYPTION_KEY:
+ default:
+ break;
+ }
+ isEmptyList = false;
+ }
+
+ return;
+}
+
+void RefreshCred()
+{
+ OCStackResult ocResult = OC_STACK_ERROR;
+ uint8_t *secPayload = NULL;
+ size_t payloadSize = 0;
+
+ OicSecCred_t *credList = NULL;
+ OicSecCred_t *cred = NULL;
+ OicSecCred_t *tmpCred = NULL;
+ //Load security resource data from SVR DB.
+ ocResult = GetSecureVirtualDatabaseFromPS(OIC_JSON_CRED_NAME, &secPayload, &payloadSize);
+ if (OC_STACK_OK != ocResult)
+ {
+ OIC_LOG_V(WARNING, TAG, "GetSecureVirtualDatabaseFromPS : %d", ocResult);
+ return;
+ }
+ if (secPayload && 0 != payloadSize)
+ {
+ ocResult = CBORPayloadToCred(secPayload, payloadSize, &credList);
+ if (OC_STACK_OK != ocResult)
+ {
+ OIC_LOG_V(DEBUG, TAG, "CBORPayloadToCred : %d", ocResult);
+ OICFree(secPayload);
+ return;
+ }
+ }
+ OICFree(secPayload);
+ DeInitCredResource();
+
+ //Add the loaded credentials into gCred of CredResource module in order to use the credential management mechanism.
+ LL_FOREACH_SAFE(credList, cred, tmpCred)
+ {
+ ocResult = AddCredential(cred);
+ if (OC_STACK_OK != ocResult)
+ {
+ OIC_LOG_V(DEBUG, TAG, "AddCredential : %d", ocResult);
+ OICFree(credList);
+ return;
+ }
+ }
+}
+
+static FILE *SVRDBFopen(const char *path, const char *mode)
+{
+ (void)path; // unused |path| parameter
+ return fopen(g_svrDbPath, mode);
+}
+
+static int MainOperation(char * svrpath, mbedtls_x509_crt * crt, mbedtls_pk_context * pkey)
+{
+ OCStackResult ocResult = OC_STACK_ERROR;
+ // initialize persistent storage for SVR DB
+ static OCPersistentStorage psInst =
+ {
+ .open = SVRDBFopen,
+ .read = fread,
+ .write = fwrite,
+ .close = fclose,
+ .unlink = unlink
+ };
+
+ if (!svrpath)
+ {
+ OIC_LOG(DEBUG, TAG, "Incorrect file path");
+ return -1;
+ }
+
+ strncpy(g_svrDbPath, svrpath, sizeof(g_svrDbPath) - 1);
+ g_svrDbPath[sizeof(g_svrDbPath) - 1] = '\0';
+
+ ocResult = InitPersistentStorageInterface();
+ if (OC_STACK_OK != ocResult)
+ {
+ OIC_LOG_V(DEBUG, TAG, "InitPersistentStorageInterface error : %d", ocResult);
+ return -1;
+ }
+
+ ocResult = OCRegisterPersistentStorageHandler(&psInst);
+ if (OC_STACK_OK != ocResult)
+ {
+ OIC_LOG_V(DEBUG, TAG, "OCRegisterPersistentStorageHandler : %d", ocResult);
+ return -1;
+ }
+
+ RefreshCred();
+ PrintCredList(GetCredList(), crt, pkey);
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ OIC_LOG(DEBUG, TAG, "OCServer is starting...");
+
+ int opt;
+ char cert_file[4096] = {0,};
+ char key_file[4096] = {0,};
+ char key_pass[32] = {0,};
+
+ // Set options
+ while ((opt = getopt(argc, argv, "c:k:p:")) != -1)
+ {
+ switch (opt)
+ {
+ case 'c':
+ strncpy(cert_file, optarg, sizeof(cert_file) - 1);
+ printf("Set own certificate file : %s\n", cert_file);
+ break;
+ case 'k':
+ strncpy(key_file, optarg, sizeof(key_file) - 1);
+ printf("Set private key file : %s\n", key_file);
+ break;
+ case 'p':
+ strncpy(key_pass, optarg, sizeof(key_pass) - 1);
+ printf("Set private key password : %s\n", key_pass);
+ break;
+ default:
+ printf("Not set any options\n");
+ }
+ }
+
+ mbedtls_ssl_config config;
+ mbedtls_ssl_config * conf = &config;
+ mbedtls_ssl_config_init( conf );
+
+ mbedtls_pk_context pkey;
+ mbedtls_x509_crt crt;
+ mbedtls_x509_crt_init(&crt);
+ mbedtls_pk_init(&pkey);
+
+ MainOperation(CRED_FILE, &crt, &pkey);
+
+ int ret = mbedtls_ssl_conf_own_cert(conf, &crt, &pkey);
+
+ int len;
+ mbedtls_net_context listen_fd, client_fd;
+ unsigned char buf[1024];
+ const char *pers = "ssl_server";
+
+ mbedtls_entropy_context entropy;
+ mbedtls_ctr_drbg_context ctr_drbg;
+ mbedtls_ssl_context ssl;
+#if defined(MBEDTLS_SSL_CACHE_C)
+ mbedtls_ssl_cache_context cache;
+#endif
+
+ mbedtls_net_init( &listen_fd );
+ mbedtls_net_init( &client_fd );
+ mbedtls_ssl_init( &ssl );
+#if defined(MBEDTLS_SSL_CACHE_C)
+ mbedtls_ssl_cache_init( &cache );
+#endif
+ mbedtls_entropy_init( &entropy );
+ mbedtls_ctr_drbg_init( &ctr_drbg );
+
+#if defined(MBEDTLS_DEBUG_C)
+ mbedtls_debug_set_threshold( DEBUG_LEVEL );
+#endif
+
+ mbedtls_printf( " ok\n" );
+
+ /*
+ * 2. Setup the listening TCP socket
+ */
+ mbedtls_printf( " . Bind on https://localhost:%s/ ...", PORT );
+ fflush( stdout );
+
+ if( ( ret = mbedtls_net_bind( &listen_fd, NULL, PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret );
+ goto exit;
+ }
+
+ mbedtls_printf( " ok\n" );
+
+ /*
+ * 3. Seed the RNG
+ */
+ mbedtls_printf( " . Seeding the random number generator..." );
+ fflush( stdout );
+
+ if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
+ (const unsigned char *) pers,
+ strlen( pers ) ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
+ goto exit;
+ }
+
+ mbedtls_printf( " ok\n" );
+
+ /*
+ * 4. Setup stuff
+ */
+ mbedtls_printf( " . Setting up the SSL data...." );
+ fflush( stdout );
+
+ if( ( ret = mbedtls_ssl_config_defaults( conf,
+ MBEDTLS_SSL_IS_SERVER,
+ MBEDTLS_SSL_TRANSPORT_STREAM,
+ MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
+ goto exit;
+ }
+
+ mbedtls_ssl_conf_rng( conf, mbedtls_ctr_drbg_random, &ctr_drbg );
+
+#if defined(MBEDTLS_SSL_CACHE_C)
+ mbedtls_ssl_conf_session_cache( conf, &cache,
+ mbedtls_ssl_cache_get,
+ mbedtls_ssl_cache_set );
+#endif
+
+ mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE);
+
+ if( ( ret = mbedtls_ssl_setup( &ssl, conf ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
+ goto exit;
+ }
+
+ mbedtls_printf( " ok\n" );
+
+reset:
+#ifdef MBEDTLS_ERROR_C
+ if( ret != 0 )
+ {
+ char error_buf[100];
+ mbedtls_strerror( ret, error_buf, 100 );
+ mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf );
+ }
+#endif
+
+ mbedtls_net_free( &client_fd );
+
+ mbedtls_ssl_session_reset( &ssl );
+
+ /*
+ * 3. Wait until a client connects
+ */
+ mbedtls_printf( " . Waiting for a remote connection ..." );
+ fflush( stdout );
+
+ if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
+ NULL, 0, NULL ) ) != 0 )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret );
+ goto exit;
+ }
+
+ mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+
+ mbedtls_printf( " ok\n" );
+
+ /*
+ * 5. Handshake
+ */
+ mbedtls_printf( " . Performing the SSL/TLS handshake..." );
+ fflush( stdout );
+
+ while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
+ {
+ if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret );
+ goto reset;
+ }
+ }
+
+ mbedtls_printf( " ok\n" );
+
+ /*
+ * 6. Read the HTTP Request
+ */
+ mbedtls_printf( " < Read from client:" );
+ fflush( stdout );
+
+ do
+ {
+ len = sizeof( buf ) - 1;
+ memset( buf, 0, sizeof( buf ) );
+ ret = mbedtls_ssl_read( &ssl, buf, len );
+
+ if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
+ continue;
+
+ if( ret <= 0 )
+ {
+ switch( ret )
+ {
+ case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+ mbedtls_printf( " connection was closed gracefully\n" );
+ break;
+
+ case MBEDTLS_ERR_NET_CONN_RESET:
+ mbedtls_printf( " connection was reset by peer\n" );
+ break;
+
+ default:
+ mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret );
+ break;
+ }
+
+ break;
+ }
+
+ len = ret;
+ mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf );
+
+ if( ret > 0 )
+ break;
+ }
+ while( 1 );
+
+ /*
+ * 7. Write the 200 Response
+ */
+ mbedtls_printf( " > Write to client:" );
+ fflush( stdout );
+
+ len = sprintf( (char *) buf, HTTP_RESPONSE,
+ mbedtls_ssl_get_ciphersuite( &ssl ) );
+
+ while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 )
+ {
+ if( ret == MBEDTLS_ERR_NET_CONN_RESET )
+ {
+ mbedtls_printf( " failed\n ! peer closed the connection\n\n" );
+ goto reset;
+ }
+
+ if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
+ goto exit;
+ }
+ }
+
+ len = ret;
+ mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf );
+
+ mbedtls_printf( " . Closing the connection..." );
+
+ while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 )
+ {
+ if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
+ ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+ {
+ mbedtls_printf( " failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret );
+ goto reset;
+ }
+ }
+
+ mbedtls_printf( " ok\n" );
+
+ ret = 0;
+ goto reset;
+
+exit:
+
+#ifdef MBEDTLS_ERROR_C
+ if( ret != 0 )
+ {
+ char error_buf[100];
+ mbedtls_strerror( ret, error_buf, 100 );
+ mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf );
+ }
+#endif
+
+ mbedtls_net_free( &client_fd );
+ mbedtls_net_free( &listen_fd );
+
+ mbedtls_x509_crt_free( &crt );
+ mbedtls_pk_free( &pkey );
+ mbedtls_ssl_free( &ssl );
+ mbedtls_ssl_config_free( &config );
+#if defined(MBEDTLS_SSL_CACHE_C)
+ mbedtls_ssl_cache_free( &cache );
+#endif
+ mbedtls_ctr_drbg_free( &ctr_drbg );
+ mbedtls_entropy_free( &entropy );
+
+#if defined(_WIN32)
+ mbedtls_printf( " Press Enter to exit this program.\n" );
+ fflush( stdout ); getchar();
+#endif
+
+ return( ret );
+}
+